diff --git a/application/src/main/data/json/system/scada_symbols/bottom-flow-meter.svg b/application/src/main/data/json/system/scada_symbols/bottom-flow-meter.svg index 9f85ccdb73..93c496f2e3 100644 --- a/application/src/main/data/json/system/scada_symbols/bottom-flow-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/bottom-flow-meter.svg @@ -51,6 +51,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "value", "stateRenderFunction": "var value = ctx.values.value;\nctx.api.text(element, value.toFixed(0));\n", @@ -78,13 +83,32 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 0, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_TIME_SERIES", + "defaultValue": 0, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "flowRate" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -93,13 +117,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -108,13 +152,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -123,13 +187,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "broken", @@ -138,13 +222,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.broken}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "displayClick", @@ -153,13 +257,16 @@ "group": "{i18n:scada.symbol.display}", "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } }, { "id": "fluid", @@ -168,13 +275,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", @@ -183,13 +310,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", @@ -198,13 +345,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", @@ -213,13 +380,32 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", @@ -228,13 +414,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -509,6 +715,22 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> @@ -703,7 +925,7 @@ - 0m³/hr + 0m³/hr diff --git a/application/src/main/data/json/system/scada_symbols/bottom-right-elbow-pipe.svg b/application/src/main/data/json/system/scada_symbols/bottom-right-elbow-pipe.svg index e27c2deee9..b3f6488f3e 100644 --- a/application/src/main/data/json/system/scada_symbols/bottom-right-elbow-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/bottom-right-elbow-pipe.svg @@ -30,6 +30,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "vertical-fluid", "stateRenderFunction": "var fluid = ctx.values.fluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}\n", @@ -41,71 +46,175 @@ "id": "fluid", "name": "{i18n:scada.symbol.fluid-presence}", "hint": "{i18n:scada.symbol.fluid-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", "name": "{i18n:scada.symbol.flow-presence}", "hint": "{i18n:scada.symbol.flow-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", "name": "{i18n:scada.symbol.flow-direction}", "hint": "{i18n:scada.symbol.flow-direction-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", "name": "{i18n:scada.symbol.flow-animation-speed}", "hint": "{i18n:scada.symbol.flow-animation-speed-hint}", + "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -124,18 +233,34 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + - + diff --git a/application/src/main/data/json/system/scada_symbols/bottom-tee-pipe.svg b/application/src/main/data/json/system/scada_symbols/bottom-tee-pipe.svg index 5fdc3fc3a2..9e44380509 100644 --- a/application/src/main/data/json/system/scada_symbols/bottom-tee-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/bottom-tee-pipe.svg @@ -40,6 +40,11 @@ "stateRenderFunction": "var fluid = (ctx.values.leftFluid || ctx.values.rightFluid ||\n ctx.values.bottomFluid) && !ctx.values.leak;\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "right-fluid", "stateRenderFunction": "var fluid = ctx.values.rightFluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", @@ -59,13 +64,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlow", @@ -74,13 +99,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlowDirection", @@ -89,13 +134,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlowAnimationSpeed", @@ -104,13 +169,32 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFluid", @@ -119,13 +203,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlow", @@ -134,13 +238,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlowDirection", @@ -149,13 +273,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlowAnimationSpeed", @@ -164,13 +308,32 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFluid", @@ -179,13 +342,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlow", @@ -194,13 +377,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlowDirection", @@ -209,13 +412,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlowAnimationSpeed", @@ -224,27 +447,67 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -295,13 +558,29 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + diff --git a/application/src/main/data/json/system/scada_symbols/centrifugal-pump.svg b/application/src/main/data/json/system/scada_symbols/centrifugal-pump.svg index 8b136687a0..c1bef78aa5 100644 --- a/application/src/main/data/json/system/scada_symbols/centrifugal-pump.svg +++ b/application/src/main/data/json/system/scada_symbols/centrifugal-pump.svg @@ -67,13 +67,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.running}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "running" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -82,13 +102,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -97,13 +137,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -112,13 +172,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rotationAnimationSpeed", @@ -127,13 +207,32 @@ "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "click", @@ -142,13 +241,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [ diff --git a/application/src/main/data/json/system/scada_symbols/cross-pipe.svg b/application/src/main/data/json/system/scada_symbols/cross-pipe.svg index b36b70b865..bfed29df3a 100644 --- a/application/src/main/data/json/system/scada_symbols/cross-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/cross-pipe.svg @@ -40,6 +40,11 @@ "stateRenderFunction": "var fluid = (ctx.values.leftFluid || ctx.values.rightFluid ||\n ctx.values.topFluid || ctx.values.bottomFluid) && !ctx.values.leak;\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "right-fluid", "stateRenderFunction": "var fluid = ctx.values.rightFluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", @@ -69,13 +74,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlow", @@ -84,13 +109,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlowDirection", @@ -99,13 +144,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlowAnimationSpeed", @@ -114,13 +179,32 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFluid", @@ -129,13 +213,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlow", @@ -144,13 +248,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlowDirection", @@ -159,13 +283,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlowAnimationSpeed", @@ -174,13 +318,32 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFluid", @@ -189,13 +352,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlow", @@ -204,13 +387,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlowDirection", @@ -219,13 +422,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlowAnimationSpeed", @@ -234,13 +457,32 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFluid", @@ -249,13 +491,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlow", @@ -264,13 +526,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlowDirection", @@ -279,13 +561,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlowAnimationSpeed", @@ -294,27 +596,67 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -381,18 +723,34 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + - + diff --git a/application/src/main/data/json/system/scada_symbols/horizontal-ball-valve.svg b/application/src/main/data/json/system/scada_symbols/horizontal-ball-valve.svg index faad4a5ba5..da140b4383 100644 --- a/application/src/main/data/json/system/scada_symbols/horizontal-ball-valve.svg +++ b/application/src/main/data/json/system/scada_symbols/horizontal-ball-valve.svg @@ -37,13 +37,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.opened}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "open", @@ -52,13 +72,32 @@ "group": null, "type": "action", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": true, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": { + "action": "SET_ATTRIBUTE", + "executeRpc": { + "method": "setState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "setAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "putTimeSeries": { + "key": "state" + }, + "valueToData": { + "type": "CONSTANT", + "constantValue": true, + "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" + } + }, + "defaultWidgetActionSettings": null }, { "id": "close", @@ -67,13 +106,32 @@ "group": null, "type": "action", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": { + "action": "SET_ATTRIBUTE", + "executeRpc": { + "method": "setState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "setAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "putTimeSeries": { + "key": "state" + }, + "valueToData": { + "type": "CONSTANT", + "constantValue": false, + "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" + } + }, + "defaultWidgetActionSettings": null } ], "properties": [ diff --git a/application/src/main/data/json/system/scada_symbols/horizontal-inline-flow-meter.svg b/application/src/main/data/json/system/scada_symbols/horizontal-inline-flow-meter.svg index 30caf224e5..8b34deaffd 100644 --- a/application/src/main/data/json/system/scada_symbols/horizontal-inline-flow-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/horizontal-inline-flow-meter.svg @@ -1,4 +1,5 @@ -{ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="200" fill="none" version="1.1" viewBox="0 0 400 200"> +<tb:metadata xmlns=""><![CDATA[{ "title": "Horizontal inline flow meter", "description": "Horizontal inline flow meter component used to display flow related value and render various states. Includes pipe fluid and leak visualizations.", "searchTags": [ @@ -50,6 +51,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "value", "stateRenderFunction": "var value = ctx.values.value;\nctx.api.text(element, value.toFixed(0));\n", @@ -77,13 +83,32 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 0, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_TIME_SERIES", + "defaultValue": 0, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "flowRate" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -92,13 +117,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -107,13 +152,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -122,13 +187,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "broken", @@ -137,13 +222,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.broken}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "displayClick", @@ -152,13 +257,16 @@ "group": "{i18n:scada.symbol.display}", "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } }, { "id": "fluid", @@ -167,13 +275,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", @@ -182,13 +310,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", @@ -197,13 +345,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", @@ -212,13 +380,32 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", @@ -227,13 +414,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -508,10 +715,25 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] -} - +}]]> @@ -683,7 +905,7 @@ - 0m³/hr + 0m³/hr diff --git a/application/src/main/data/json/system/scada_symbols/horizontal-pipe.svg b/application/src/main/data/json/system/scada_symbols/horizontal-pipe.svg index 63c8373541..d2ddc67657 100644 --- a/application/src/main/data/json/system/scada_symbols/horizontal-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/horizontal-pipe.svg @@ -23,6 +23,11 @@ "tag": "leak", "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null } ], "behavior": [ @@ -30,71 +35,175 @@ "id": "fluid", "name": "{i18n:scada.symbol.fluid-presence}", "hint": "{i18n:scada.symbol.fluid-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", "name": "{i18n:scada.symbol.flow-presence}", "hint": "{i18n:scada.symbol.flow-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", "name": "{i18n:scada.symbol.flow-direction}", "hint": "{i18n:scada.symbol.flow-direction-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", "name": "{i18n:scada.symbol.flow-animation-speed}", "hint": "{i18n:scada.symbol.flow-animation-speed-hint}", + "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -113,12 +222,37 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] -}]]> - +}]]> + + + + + + - + + + + + @@ -272,11 +406,7 @@ - - - - - + diff --git a/application/src/main/data/json/system/scada_symbols/horizontal-tank-with-screen.svg b/application/src/main/data/json/system/scada_symbols/horizontal-tank-with-screen.svg deleted file mode 100644 index bfc7c83976..0000000000 --- a/application/src/main/data/json/system/scada_symbols/horizontal-tank-with-screen.svg +++ /dev/null @@ -1,20 +0,0 @@ - -{ - "title": "Horizontal tank with screen", - "widgetSizeX": 5, - "widgetSizeY": 3, - "tags": [], - "behavior": [], - "properties": [] -} - - - - - - - - - - - \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/horizontal-wheel-valve.svg b/application/src/main/data/json/system/scada_symbols/horizontal-wheel-valve.svg index 9fc03dd69a..a96f61781d 100644 --- a/application/src/main/data/json/system/scada_symbols/horizontal-wheel-valve.svg +++ b/application/src/main/data/json/system/scada_symbols/horizontal-wheel-valve.svg @@ -37,13 +37,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.opened}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "open", @@ -52,13 +72,32 @@ "group": null, "type": "action", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": true, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": { + "action": "SET_ATTRIBUTE", + "executeRpc": { + "method": "setState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "setAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "putTimeSeries": { + "key": "state" + }, + "valueToData": { + "type": "CONSTANT", + "constantValue": true, + "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" + } + }, + "defaultWidgetActionSettings": null }, { "id": "close", @@ -67,13 +106,32 @@ "group": null, "type": "action", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": { + "action": "SET_ATTRIBUTE", + "executeRpc": { + "method": "setState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "setAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "putTimeSeries": { + "key": "state" + }, + "valueToData": { + "type": "CONSTANT", + "constantValue": false, + "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" + } + }, + "defaultWidgetActionSettings": null } ], "properties": [ diff --git a/application/src/main/data/json/system/scada_symbols/left-bottom-elbow-pipe.svg b/application/src/main/data/json/system/scada_symbols/left-bottom-elbow-pipe.svg index 1109a8a54c..cd9b5f1b7a 100644 --- a/application/src/main/data/json/system/scada_symbols/left-bottom-elbow-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/left-bottom-elbow-pipe.svg @@ -29,6 +29,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "vertical-fluid", "stateRenderFunction": "var fluid = ctx.values.fluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}\n", @@ -40,71 +45,175 @@ "id": "fluid", "name": "{i18n:scada.symbol.fluid-presence}", "hint": "{i18n:scada.symbol.fluid-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", "name": "{i18n:scada.symbol.flow-presence}", "hint": "{i18n:scada.symbol.flow-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", "name": "{i18n:scada.symbol.flow-direction}", "hint": "{i18n:scada.symbol.flow-direction-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", "name": "{i18n:scada.symbol.flow-animation-speed}", "hint": "{i18n:scada.symbol.flow-animation-speed-hint}", + "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -123,19 +232,35 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + - + diff --git a/application/src/main/data/json/system/scada_symbols/left-drain-pipe.svg b/application/src/main/data/json/system/scada_symbols/left-drain-pipe.svg new file mode 100644 index 0000000000..2a5c3ce47a --- /dev/null +++ b/application/src/main/data/json/system/scada_symbols/left-drain-pipe.svg @@ -0,0 +1,166 @@ + + { + "title": "Left drain pipe", + "description": "Left drain pipe", + "searchTags": [ + "pipe", + "drain" + ], + "widgetSizeX": 2, + "widgetSizeY": 1, + "tags": [ + { + "tag": "clickArea", + "stateRenderFunction": null, + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'click');" + } + } + }, + { + "tag": "fluid-background", + "stateRenderFunction": "var color = ctx.properties.fluidColor;\nelement.attr({fill: color});", + "actions": null + }, + { + "tag": "leak", + "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", + "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + } + ], + "behavior": [ + { + "id": "click", + "name": "{i18n:scada.symbol.on-click}", + "hint": "{i18n:scada.symbol.on-click-hint}", + "group": null, + "type": "widgetAction", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } + }, + { + "id": "leak", + "name": "{i18n:scada.symbol.leak}", + "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.leak-present}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + } + ], + "properties": [ + { + "id": "fluidColor", + "name": "{i18n:scada.symbol.fluid-color}", + "type": "color", + "default": "#8CAA5C", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + } + ] +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/left-elbow-drain-pipe.svg b/application/src/main/data/json/system/scada_symbols/left-elbow-drain-pipe.svg new file mode 100644 index 0000000000..2f91847b71 --- /dev/null +++ b/application/src/main/data/json/system/scada_symbols/left-elbow-drain-pipe.svg @@ -0,0 +1,181 @@ + +{ + "title": "Left elbow drain pipe", + "description": "Left elbow drain pipe", + "searchTags": [ + "pipe", + "drain" + ], + "widgetSizeX": 2, + "widgetSizeY": 1, + "tags": [ + { + "tag": "clickArea", + "stateRenderFunction": null, + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'click');" + } + } + }, + { + "tag": "fluid-background", + "stateRenderFunction": "var color = ctx.properties.fluidColor;\nelement.attr({fill: color});", + "actions": null + }, + { + "tag": "leak", + "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", + "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + } + ], + "behavior": [ + { + "id": "click", + "name": "{i18n:scada.symbol.on-click}", + "hint": "{i18n:scada.symbol.on-click-hint}", + "group": null, + "type": "widgetAction", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } + }, + { + "id": "leak", + "name": "{i18n:scada.symbol.leak}", + "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.leak-present}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + } + ], + "properties": [ + { + "id": "fluidColor", + "name": "{i18n:scada.symbol.fluid-color}", + "type": "color", + "default": "#8CAA5C", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + } + ] +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/left-flow-meter.svg b/application/src/main/data/json/system/scada_symbols/left-flow-meter.svg index 16551bf2e9..b1da702871 100644 --- a/application/src/main/data/json/system/scada_symbols/left-flow-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/left-flow-meter.svg @@ -1,4 +1,5 @@ -{ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="400" height="400" fill="none" version="1.1" viewBox="0 0 400 400"> +<tb:metadata xmlns=""><![CDATA[{ "title": "Left flow meter", "description": "Left flow meter component used to display flow related value and render various states. Includes pipe fluid and leak visualizations.", "searchTags": [ @@ -50,6 +51,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "value", "stateRenderFunction": "var value = ctx.values.value;\nctx.api.text(element, value.toFixed(0));\n", @@ -77,13 +83,32 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 0, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_TIME_SERIES", + "defaultValue": 0, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "flowRate" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -92,13 +117,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -107,13 +152,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -122,13 +187,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "broken", @@ -137,13 +222,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.broken}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "displayClick", @@ -152,13 +257,16 @@ "group": "{i18n:scada.symbol.display}", "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } }, { "id": "fluid", @@ -167,13 +275,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", @@ -182,13 +310,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", @@ -197,13 +345,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", @@ -212,13 +380,32 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", @@ -227,13 +414,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -508,10 +715,25 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] -} - +}]]> @@ -697,7 +919,7 @@ - 0m³/hr + 0m³/hr diff --git a/application/src/main/data/json/system/scada_symbols/left-motor-pump.svg b/application/src/main/data/json/system/scada_symbols/left-motor-pump.svg index 271a4a27c2..5be0a454e5 100644 --- a/application/src/main/data/json/system/scada_symbols/left-motor-pump.svg +++ b/application/src/main/data/json/system/scada_symbols/left-motor-pump.svg @@ -1,5 +1,4 @@ - - { +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="800" height="600" fill="none" version="1.1" viewBox="0 0 800 600"><tb:metadata xmlns=""><![CDATA[{ "title": "Left motor pump", "description": "Left motor pump with configurable states.", "searchTags": [ @@ -32,13 +31,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.running}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "running" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -47,13 +66,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -62,13 +101,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -77,13 +136,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "click", @@ -92,13 +171,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [ @@ -168,8 +250,7 @@ } ] } - - + @@ -441,70 +522,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/left-tee-pipe.svg b/application/src/main/data/json/system/scada_symbols/left-tee-pipe.svg index 43106f9791..a0e01f639b 100644 --- a/application/src/main/data/json/system/scada_symbols/left-tee-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/left-tee-pipe.svg @@ -40,6 +40,11 @@ "stateRenderFunction": "var fluid = (ctx.values.leftFluid ||\n ctx.values.topFluid || ctx.values.bottomFluid) && !ctx.values.leak;\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "top-fluid", "stateRenderFunction": "var fluid = ctx.values.topFluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", @@ -59,13 +64,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlow", @@ -74,13 +99,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlowDirection", @@ -89,13 +134,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlowAnimationSpeed", @@ -104,13 +169,32 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFluid", @@ -119,13 +203,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlow", @@ -134,13 +238,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlowDirection", @@ -149,13 +273,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlowAnimationSpeed", @@ -164,13 +308,32 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFluid", @@ -179,13 +342,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlow", @@ -194,13 +377,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlowDirection", @@ -209,13 +412,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlowAnimationSpeed", @@ -224,27 +447,67 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -295,13 +558,29 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + diff --git a/application/src/main/data/json/system/scada_symbols/left-top-elbow-pipe.svg b/application/src/main/data/json/system/scada_symbols/left-top-elbow-pipe.svg index 1b795935e1..276f3aa004 100644 --- a/application/src/main/data/json/system/scada_symbols/left-top-elbow-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/left-top-elbow-pipe.svg @@ -29,6 +29,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "vertical-fluid", "stateRenderFunction": "var fluid = ctx.values.fluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}\n", @@ -40,71 +45,175 @@ "id": "fluid", "name": "{i18n:scada.symbol.fluid-presence}", "hint": "{i18n:scada.symbol.fluid-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", "name": "{i18n:scada.symbol.flow-presence}", "hint": "{i18n:scada.symbol.flow-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", "name": "{i18n:scada.symbol.flow-direction}", "hint": "{i18n:scada.symbol.flow-direction-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", "name": "{i18n:scada.symbol.flow-animation-speed}", "hint": "{i18n:scada.symbol.flow-animation-speed-hint}", + "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -123,19 +232,35 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + - + diff --git a/application/src/main/data/json/system/scada_symbols/level_and_fan.svg b/application/src/main/data/json/system/scada_symbols/level_and_fan.svg deleted file mode 100644 index 9757228504..0000000000 --- a/application/src/main/data/json/system/scada_symbols/level_and_fan.svg +++ /dev/null @@ -1,318 +0,0 @@ - -{ - "title": "Level and Fan", - "description": "Level and Fan Symbol", - "searchTags": [ - "level", - "fan" - ], - "widgetSizeX": 3, - "widgetSizeY": 3, - "stateRenderFunction": "var showMinMaxLevel = ctx.properties.showMinMaxLevel;\nvar minLevelElement = ctx.tags.minLevel[0];\nvar maxLevelElement = ctx.tags.maxLevel[0];\nvar minLevel = ctx.properties.minLevel; \nvar maxLevel = ctx.properties.maxLevel;\n\nif (showMinMaxLevel) {\n \n var minMaxLevelFont = ctx.properties.minMaxLevelFont;\n var minMaxLevelColor = ctx.properties.minMaxLevelColor;\n \n ctx.api.text(minLevelElement, minLevel);\n ctx.api.text(maxLevelElement, maxLevel);\n \n ctx.api.font(minLevelElement, minMaxLevelFont, minMaxLevelColor);\n ctx.api.font(maxLevelElement, minMaxLevelFont, minMaxLevelColor);\n \n} else {\n minLevelElement.hide();\n maxLevelElement.hide();\n}\n\nvar disabled = ctx.values.disabled;\nvar on = ctx.values.on;\nvar level = ctx.values.level;\n\nvar onButton = ctx.tags.onButton;\nvar offButton = ctx.tags.offButton;\nvar levelUpButton = ctx.tags.levelUpButton;\nvar levelDownButton = ctx.tags.levelDownButton;\n\nvar onButtonEnabled = !disabled && !on;\nvar offButtonEnabled = !disabled && on;\nvar levelUpEnabled = !disabled && level < maxLevel;\nvar levelDownEnabled = !disabled && level > minLevel;\n\nif (onButtonEnabled) {\n ctx.api.enable(onButton);\n onButton[0].findOne('rect').attr({fill: '#12ed19'});\n} else {\n ctx.api.disable(onButton);\n onButton[0].findOne('rect').attr({fill: '#777'});\n}\n \nif (offButtonEnabled) {\n ctx.api.enable(offButton);\n offButton[0].findOne('rect').attr({fill: '#ed121f'});\n} else {\n ctx.api.disable(offButton);\n offButton[0].findOne('rect').attr({fill: '#777'});\n} \n\n\nif (levelUpEnabled) {\n ctx.api.enable(levelUpButton);\n levelUpButton[0].findOne('rect').attr({fill: '#fff'});\n} else {\n ctx.api.disable(levelUpButton);\n levelUpButton[0].findOne('rect').attr({fill: '#777'});\n}\n \nif (levelDownEnabled) {\n ctx.api.enable(levelDownButton);\n levelDownButton[0].findOne('rect').attr({fill: '#fff'});\n} else {\n ctx.api.disable(levelDownButton);\n levelDownButton[0].findOne('rect').attr({fill: '#777'});\n}", - "tags": [ - { - "tag": "fan", - "stateRenderFunction": "var on = ctx.values.on;\nvar hasAnimation = element.remember('hasAnimation');\nif (on) {\n\n var level = ctx.values.level; \n var minLevel = ctx.properties.minLevel; \n var maxLevel = ctx.properties.maxLevel;\n\n var speed = (level - minLevel) / (maxLevel - minLevel);\n speed = Math.max(0, Math.min(1, speed))*2; \n\n if (!hasAnimation) {\n element.remember('hasAnimation', true);\n element.animate(1000).ease('-').rotate(360).loop();\n } else {\n element.timeline().play();\n }\n element.timeline().speed(speed);\n} else {\n if (hasAnimation) {\n element.timeline().pause();\n }\n}\n", - "actions": null - }, - { - "tag": "level", - "stateRenderFunction": "var level = ctx.values.level; \nvar disabled = ctx.values.disabled;\nvar minLevel = ctx.properties.minLevel; \nvar maxLevel = ctx.properties.maxLevel;\n\nvar height = (level - minLevel) / (maxLevel - minLevel);\nheight = Math.max(0, Math.min(1, height))*80; \n\nctx.api.animate(element, 200).attr({height: height});\n\nvar fill;\nif (disabled) {\n fill = ctx.properties.disabledLevelBackground;\n} else {\n var colorProcessor = ctx.properties.levelBackground;\n colorProcessor.update(level);\n fill = colorProcessor.color;\n}\n\nelement.attr({fill: fill});", - "actions": null - }, - { - "tag": "levelDownButton", - "actions": { - "click": { - "actionFunction": "var level = ctx.values.level; \nvar minLevel = ctx.properties.minLevel;\n\nvar newLevel = Math.max(minLevel, level - 5);\nctx.api.setValue('level', newLevel);\nctx.api.callAction(event, 'levelUpdateState', newLevel, {\n error: () => {\n ctx.api.setValue('level', level);\n }\n});" - } - } - }, - { - "tag": "levelTitle", - "stateRenderFunction": "var showLevelTitle = ctx.properties.showLevelTitle;\n\nif (showLevelTitle) {\n var levelTitle = ctx.properties.levelTitle;\n var levelTitleFont = ctx.properties.levelTitleFont;\n var levelTitleColor = ctx.properties.levelTitleColor;\n \n ctx.api.text(element, levelTitle);\n ctx.api.font(element, levelTitleFont, levelTitleColor);\n \n} else {\n element.hide();\n}", - "actions": null - }, - { - "tag": "levelUpButton", - "actions": { - "click": { - "actionFunction": "var level = ctx.values.level; \nvar maxLevel = ctx.properties.maxLevel;\n\nvar newLevel = Math.min(maxLevel, level + 5);\nctx.api.setValue('level', newLevel);\nctx.api.callAction(event, 'levelUpdateState', newLevel, {\n error: () => {\n ctx.api.setValue('level', level);\n }\n});" - } - } - }, - { - "tag": "levelValue", - "stateRenderFunction": "var showValue = ctx.properties.showValue;\n\nif (showValue) {\n var valueFont = ctx.properties.valueFont;\n var valueColor = ctx.properties.valueColor;\n var level = ctx.values.level; \n \n var levelText = ctx.api.formatValue(level, ctx.properties.valueDecimals, ctx.properties.valueUnits, false);\n\n ctx.api.font(element, valueFont, valueColor);\n ctx.api.text(element, levelText);\n\n} else {\n element.hide();\n ctx.tags.levelValueBackground[0].hide();\n}", - "actions": { - "click": { - "actionFunction": "ctx.api.callAction(event, 'levelValueClick');" - } - } - }, - { - "tag": "offButton", - "actions": { - "click": { - "actionFunction": "ctx.api.callAction(event, 'offUpdateState', undefined, {\n next: () => {\n ctx.api.setValue('on', false);\n }\n});\n" - } - } - }, - { - "tag": "onButton", - "actions": { - "click": { - "actionFunction": "ctx.api.callAction(event, 'onUpdateState', undefined, {\n next: () => {\n ctx.api.setValue('on', true);\n }\n});\n\n" - } - } - }, - { - "tag": "ramka", - "stateRenderFunction": "var on = ctx.values.on;\nvar hasAnimation = element.remember('hasAnimation');\nif (on) {\n if (!hasAnimation) {\n element.remember('hasAnimation', true);\n ctx.api.animate(element, 1000).scale(1.1).loop(0, true);\n } else {\n element.timeline().play();\n }\n} else {\n if (hasAnimation) {\n element.timeline().pause();\n }\n}", - "actions": null - } - ], - "behavior": [ - { - "id": "level", - "name": "Level", - "hint": null, - "type": "value", - "valueType": "DOUBLE", - "defaultValue": 10, - "trueLabel": null, - "falseLabel": null, - "stateLabel": null, - "valueToDataType": null, - "constantValue": null, - "valueToDataFunction": null - }, - { - "id": "disabled", - "name": "{i18n:widgets.rpc-state.disabled-state}", - "hint": "{i18n:widgets.rpc-state.disabled-state-hint}", - "type": "value", - "valueType": "BOOLEAN", - "defaultValue": false, - "trueLabel": "", - "falseLabel": "", - "stateLabel": "{i18n:widgets.rpc-state.disabled}", - "valueToDataType": null, - "constantValue": null, - "valueToDataFunction": null - }, - { - "id": "on", - "name": "On/Off state", - "hint": null, - "type": "value", - "valueType": "BOOLEAN", - "defaultValue": true, - "trueLabel": "{i18n:widgets.rpc-state.on}", - "falseLabel": "{i18n:widgets.rpc-state.off}", - "stateLabel": "{i18n:widgets.rpc-state.on}", - "valueToDataType": null, - "constantValue": null, - "valueToDataFunction": null - }, - { - "id": "onUpdateState", - "name": "{i18n:widgets.rpc-state.turn-on}", - "hint": "{i18n:widgets.rpc-state.turn-on-hint}", - "type": "action", - "valueType": "BOOLEAN", - "valueToDataType": "CONSTANT", - "constantValue": true - }, - { - "id": "offUpdateState", - "name": "{i18n:widgets.rpc-state.turn-off}", - "hint": "{i18n:widgets.rpc-state.turn-off-hint}", - "type": "action", - "valueType": "BOOLEAN", - "valueToDataType": "CONSTANT", - "constantValue": false - }, - { - "id": "levelUpdateState", - "name": "Update level", - "type": "action", - "valueType": "DOUBLE", - "valueToDataType": "VALUE", - "constantValue": 0 - }, - { - "id": "levelValueClick", - "name": "On level value click", - "type": "widgetAction" - } - ], - "properties": [ - { - "id": "showLevelTitle", - "name": "Level title", - "type": "switch", - "default": true, - "rowClass": "column-xs" - }, - { - "id": "levelTitle", - "name": "Level title", - "type": "text", - "default": "{i18n:widgets.battery-level.value}", - "disableOnProperty": "showLevelTitle", - "fieldClass": "flex" - }, - { - "id": "levelTitleFont", - "name": "Level title", - "type": "font", - "default": { - "size": 6, - "sizeUnit": "px", - "family": "Roboto", - "weight": "normal", - "style": "normal" - }, - "disableOnProperty": "showLevelTitle" - }, - { - "id": "levelTitleColor", - "name": "Level title", - "type": "color", - "default": "#000000", - "disableOnProperty": "showLevelTitle" - }, - { - "id": "showValue", - "name": "Value", - "type": "switch", - "default": true, - "rowClass": "column-xs" - }, - { - "id": "valueUnits", - "name": "Value", - "type": "units", - "default": "", - "disableOnProperty": "showValue", - "fieldClass": "flex" - }, - { - "id": "valueDecimals", - "name": "Value", - "type": "number", - "default": 2, - "min": 0, - "max": 15, - "step": 1, - "fieldSuffix": "decimals", - "disableOnProperty": "showValue", - "fieldClass": "flex" - }, - { - "id": "valueFont", - "name": "Value", - "type": "font", - "default": { - "size": 6, - "sizeUnit": "px", - "family": "Roboto", - "weight": "normal", - "style": "normal" - }, - "disableOnProperty": "showValue" - }, - { - "id": "valueColor", - "name": "Value", - "type": "color", - "default": "#000000", - "disableOnProperty": "showValue" - }, - { - "id": "minLevel", - "name": "Level range", - "subLabel": "min", - "type": "number", - "required": true, - "default": 0, - "min": 0, - "rowClass": "column-xs", - "fieldClass": "flex-xs" - }, - { - "id": "maxLevel", - "name": "Level range", - "subLabel": "max", - "type": "number", - "required": true, - "default": 100, - "min": 0, - "fieldClass": "flex-xs" - }, - { - "id": "showMinMaxLevel", - "name": "Min/Max label", - "type": "switch", - "default": true - }, - { - "id": "minMaxLevelFont", - "name": "Min/Max label", - "type": "font", - "default": { - "size": 6, - "sizeUnit": "px", - "family": "Roboto", - "weight": "normal", - "style": "normal" - }, - "disableOnProperty": "showMinMaxLevel" - }, - { - "id": "minMaxLevelColor", - "name": "Min/Max label", - "type": "color", - "default": "#666", - "disableOnProperty": "showMinMaxLevel" - }, - { - "id": "levelBackground", - "name": "Level background", - "subLabel": "Enabled", - "type": "color_settings", - "default": { - "type": "constant", - "color": "#1abb48", - "colorFunction": "return value > 70 ? '#d5280d' : '#1abb48';" - }, - "divider": true, - "rowClass": "column-xs" - }, - { - "id": "disabledLevelBackground", - "name": "Level background", - "subLabel": "Disabled", - "type": "color", - "default": "#ccc" - } - ] -}min - N/A - Level - max - - - On - - - Off - - - - - - - - \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/long-bottom-filter.svg b/application/src/main/data/json/system/scada_symbols/long-bottom-filter.svg index f368fdbc4d..d9defd33d9 100644 --- a/application/src/main/data/json/system/scada_symbols/long-bottom-filter.svg +++ b/application/src/main/data/json/system/scada_symbols/long-bottom-filter.svg @@ -26,13 +26,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [] diff --git a/application/src/main/data/json/system/scada_symbols/long-horizontal-pipe.svg b/application/src/main/data/json/system/scada_symbols/long-horizontal-pipe.svg index 5ab59e56e5..ffc77b0ac0 100644 --- a/application/src/main/data/json/system/scada_symbols/long-horizontal-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/long-horizontal-pipe.svg @@ -23,6 +23,11 @@ "tag": "leak", "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null } ], "behavior": [ @@ -30,71 +35,175 @@ "id": "fluid", "name": "{i18n:scada.symbol.fluid-presence}", "hint": "{i18n:scada.symbol.fluid-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", "name": "{i18n:scada.symbol.flow-presence}", "hint": "{i18n:scada.symbol.flow-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", "name": "{i18n:scada.symbol.flow-direction}", "hint": "{i18n:scada.symbol.flow-direction-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", "name": "{i18n:scada.symbol.flow-animation-speed}", "hint": "{i18n:scada.symbol.flow-animation-speed-hint}", + "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -113,9 +222,25 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] -}]]> +}]]> diff --git a/application/src/main/data/json/system/scada_symbols/long-top-filter.svg b/application/src/main/data/json/system/scada_symbols/long-top-filter.svg index 676102f5a9..a63b679f0a 100644 --- a/application/src/main/data/json/system/scada_symbols/long-top-filter.svg +++ b/application/src/main/data/json/system/scada_symbols/long-top-filter.svg @@ -26,13 +26,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [] diff --git a/application/src/main/data/json/system/scada_symbols/long-vertical-pipe.svg b/application/src/main/data/json/system/scada_symbols/long-vertical-pipe.svg index 6ebb0b72cb..7f4e30edad 100644 --- a/application/src/main/data/json/system/scada_symbols/long-vertical-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/long-vertical-pipe.svg @@ -23,6 +23,11 @@ "tag": "leak", "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null } ], "behavior": [ @@ -30,71 +35,175 @@ "id": "fluid", "name": "{i18n:scada.symbol.fluid-presence}", "hint": "{i18n:scada.symbol.fluid-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", "name": "{i18n:scada.symbol.flow-presence}", "hint": "{i18n:scada.symbol.flow-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", "name": "{i18n:scada.symbol.flow-direction}", "hint": "{i18n:scada.symbol.flow-direction-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", "name": "{i18n:scada.symbol.flow-animation-speed}", "hint": "{i18n:scada.symbol.flow-animation-speed-hint}", + "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -113,9 +222,25 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] -}]]> +}]]> diff --git a/application/src/main/data/json/system/scada_symbols/right-drain-pipe.svg b/application/src/main/data/json/system/scada_symbols/right-drain-pipe.svg new file mode 100644 index 0000000000..3fe3501e16 --- /dev/null +++ b/application/src/main/data/json/system/scada_symbols/right-drain-pipe.svg @@ -0,0 +1,167 @@ +{ + "title": "Right drain pipe", + "description": "Right drain pipe", + "searchTags": [ + "pipe", + "drain" + ], + "widgetSizeX": 2, + "widgetSizeY": 1, + "tags": [ + { + "tag": "clickArea", + "stateRenderFunction": null, + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'click');" + } + } + }, + { + "tag": "fluid-background", + "stateRenderFunction": "var color = ctx.properties.fluidColor;\nelement.attr({fill: color});", + "actions": null + }, + { + "tag": "leak", + "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", + "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + } + ], + "behavior": [ + { + "id": "click", + "name": "{i18n:scada.symbol.on-click}", + "hint": "{i18n:scada.symbol.on-click-hint}", + "group": null, + "type": "widgetAction", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } + }, + { + "id": "leak", + "name": "{i18n:scada.symbol.leak}", + "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.leak-present}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + } + ], + "properties": [ + { + "id": "fluidColor", + "name": "{i18n:scada.symbol.fluid-color}", + "type": "color", + "default": "#8CAA5C", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + } + ] +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/right-elbow-drain-pipe.svg b/application/src/main/data/json/system/scada_symbols/right-elbow-drain-pipe.svg new file mode 100644 index 0000000000..14ede98e81 --- /dev/null +++ b/application/src/main/data/json/system/scada_symbols/right-elbow-drain-pipe.svg @@ -0,0 +1,178 @@ + +{ + "title": "Right elbow drain pipe", + "description": "Right elbow drain pipe", + "searchTags": [ + "pipe", + "drain" + ], + "widgetSizeX": 2, + "widgetSizeY": 1, + "tags": [ + { + "tag": "clickArea", + "stateRenderFunction": null, + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'click');" + } + } + }, + { + "tag": "fluid-background", + "stateRenderFunction": "var color = ctx.properties.fluidColor;\nelement.attr({fill: color});", + "actions": null + }, + { + "tag": "leak", + "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", + "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + } + ], + "behavior": [ + { + "id": "click", + "name": "{i18n:scada.symbol.on-click}", + "hint": "{i18n:scada.symbol.on-click-hint}", + "group": null, + "type": "widgetAction", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } + }, + { + "id": "leak", + "name": "{i18n:scada.symbol.leak}", + "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.leak-present}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + } + ], + "properties": [ + { + "id": "fluidColor", + "name": "{i18n:scada.symbol.fluid-color}", + "type": "color", + "default": "#8CAA5C", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + } + ] +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/right-flow-meter.svg b/application/src/main/data/json/system/scada_symbols/right-flow-meter.svg index d850e7b2c3..e5df51e561 100644 --- a/application/src/main/data/json/system/scada_symbols/right-flow-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/right-flow-meter.svg @@ -51,6 +51,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "value", "stateRenderFunction": "var value = ctx.values.value;\nctx.api.text(element, value.toFixed(0));\n", @@ -78,13 +83,32 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 0, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_TIME_SERIES", + "defaultValue": 0, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "flowRate" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -93,13 +117,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -108,13 +152,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -123,13 +187,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "broken", @@ -138,13 +222,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.broken}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "displayClick", @@ -153,13 +257,16 @@ "group": "{i18n:scada.symbol.display}", "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } }, { "id": "fluid", @@ -168,13 +275,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", @@ -183,13 +310,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", @@ -198,13 +345,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", @@ -213,13 +380,32 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", @@ -228,13 +414,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -509,6 +715,22 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> @@ -697,7 +919,7 @@ - + diff --git a/application/src/main/data/json/system/scada_symbols/right-motor-pump.svg b/application/src/main/data/json/system/scada_symbols/right-motor-pump.svg index c8e47a9fcc..7ada9a91e3 100644 --- a/application/src/main/data/json/system/scada_symbols/right-motor-pump.svg +++ b/application/src/main/data/json/system/scada_symbols/right-motor-pump.svg @@ -1,5 +1,4 @@ - - { +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="800" height="600" fill="none" version="1.1" viewBox="0 0 800 600"><tb:metadata xmlns=""><![CDATA[{ "title": "Right motor pump", "description": "Right motor pump with configurable states.", "searchTags": [ @@ -32,13 +31,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.running}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "running" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -47,13 +66,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -62,13 +101,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -77,13 +136,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "click", @@ -92,13 +171,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [ @@ -168,8 +250,7 @@ } ] } - - + @@ -441,70 +522,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/right-tee-pipe.svg b/application/src/main/data/json/system/scada_symbols/right-tee-pipe.svg index 05a8c3cc67..4c84999b1f 100644 --- a/application/src/main/data/json/system/scada_symbols/right-tee-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/right-tee-pipe.svg @@ -30,6 +30,11 @@ "stateRenderFunction": "var fluid = (ctx.values.rightFluid ||\n ctx.values.topFluid || ctx.values.bottomFluid) && !ctx.values.leak;\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "right-fluid", "stateRenderFunction": "var fluid = ctx.values.rightFluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", @@ -59,13 +64,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlow", @@ -74,13 +99,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlowDirection", @@ -89,13 +134,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlowAnimationSpeed", @@ -104,13 +169,32 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFluid", @@ -119,13 +203,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlow", @@ -134,13 +238,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlowDirection", @@ -149,13 +273,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlowAnimationSpeed", @@ -164,13 +308,32 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFluid", @@ -179,13 +342,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlow", @@ -194,13 +377,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlowDirection", @@ -209,13 +412,33 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "bottomFlowAnimationSpeed", @@ -224,27 +447,67 @@ "group": "{i18n:scada.symbol.bottom-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -295,13 +558,29 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + diff --git a/application/src/main/data/json/system/scada_symbols/short-bottom-filter.svg b/application/src/main/data/json/system/scada_symbols/short-bottom-filter.svg index 7a111ca5ac..b3235c5906 100644 --- a/application/src/main/data/json/system/scada_symbols/short-bottom-filter.svg +++ b/application/src/main/data/json/system/scada_symbols/short-bottom-filter.svg @@ -26,13 +26,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [] diff --git a/application/src/main/data/json/system/scada_symbols/short-left-drain-pipe.svg b/application/src/main/data/json/system/scada_symbols/short-left-drain-pipe.svg new file mode 100644 index 0000000000..ffe74a681e --- /dev/null +++ b/application/src/main/data/json/system/scada_symbols/short-left-drain-pipe.svg @@ -0,0 +1,160 @@ + + { + "title": "Short left drain pipe", + "description": "Short left drain pipe", + "searchTags": [ + "pipe", + "drain" + ], + "widgetSizeX": 1, + "widgetSizeY": 1, + "tags": [ + { + "tag": "clickArea", + "stateRenderFunction": null, + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'click');" + } + } + }, + { + "tag": "fluid-background", + "stateRenderFunction": "var color = ctx.properties.fluidColor;\nelement.attr({fill: color});", + "actions": null + }, + { + "tag": "leak", + "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", + "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + } + ], + "behavior": [ + { + "id": "click", + "name": "{i18n:scada.symbol.on-click}", + "hint": "{i18n:scada.symbol.on-click-hint}", + "group": null, + "type": "widgetAction", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } + }, + { + "id": "leak", + "name": "{i18n:scada.symbol.leak}", + "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.leak-present}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + } + ], + "properties": [ + { + "id": "fluidColor", + "name": "{i18n:scada.symbol.fluid-color}", + "type": "color", + "default": "#8CAA5C", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + } + ] +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/short-right-drain-pipe.svg b/application/src/main/data/json/system/scada_symbols/short-right-drain-pipe.svg new file mode 100644 index 0000000000..306898e3ae --- /dev/null +++ b/application/src/main/data/json/system/scada_symbols/short-right-drain-pipe.svg @@ -0,0 +1,160 @@ + + { + "title": "Short right drain pipe", + "description": "Short right drain pipe", + "searchTags": [ + "pipe", + "drain" + ], + "widgetSizeX": 1, + "widgetSizeY": 1, + "tags": [ + { + "tag": "clickArea", + "stateRenderFunction": null, + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'click');" + } + } + }, + { + "tag": "fluid-background", + "stateRenderFunction": "var color = ctx.properties.fluidColor;\nelement.attr({fill: color});", + "actions": null + }, + { + "tag": "leak", + "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", + "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + } + ], + "behavior": [ + { + "id": "click", + "name": "{i18n:scada.symbol.on-click}", + "hint": "{i18n:scada.symbol.on-click-hint}", + "group": null, + "type": "widgetAction", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } + }, + { + "id": "leak", + "name": "{i18n:scada.symbol.leak}", + "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.leak-present}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + } + ], + "properties": [ + { + "id": "fluidColor", + "name": "{i18n:scada.symbol.fluid-color}", + "type": "color", + "default": "#8CAA5C", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + } + ] +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/short-top-filter.svg b/application/src/main/data/json/system/scada_symbols/short-top-filter.svg index e0847134ea..d50eada2aa 100644 --- a/application/src/main/data/json/system/scada_symbols/short-top-filter.svg +++ b/application/src/main/data/json/system/scada_symbols/short-top-filter.svg @@ -26,13 +26,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [] diff --git a/application/src/main/data/json/system/scada_symbols/small-left-motor-pump.svg b/application/src/main/data/json/system/scada_symbols/small-left-motor-pump.svg index a0d9d937ae..85e617ff22 100644 --- a/application/src/main/data/json/system/scada_symbols/small-left-motor-pump.svg +++ b/application/src/main/data/json/system/scada_symbols/small-left-motor-pump.svg @@ -1,5 +1,4 @@ - - { +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="600" height="400" fill="none" version="1.1" viewBox="0 0 600 400"><tb:metadata xmlns=""><![CDATA[{ "title": "Small left motor pump", "description": "Small left motor pump with configurable states.", "searchTags": [ @@ -32,13 +31,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.running}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "running" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -47,13 +66,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -62,13 +101,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -77,13 +136,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "click", @@ -92,13 +171,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [ @@ -168,50 +250,7 @@ } ] } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -385,6 +424,5 @@ - - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/small-right-motor-pump.svg b/application/src/main/data/json/system/scada_symbols/small-right-motor-pump.svg index 742e1d7e6b..7b9b1c260d 100644 --- a/application/src/main/data/json/system/scada_symbols/small-right-motor-pump.svg +++ b/application/src/main/data/json/system/scada_symbols/small-right-motor-pump.svg @@ -32,13 +32,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.running}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "running" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -47,13 +67,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -62,13 +102,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -77,13 +137,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "click", @@ -92,13 +172,16 @@ "group": null, "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } } ], "properties": [ diff --git a/application/src/main/data/json/system/scada_symbols/top-flow-meter.svg b/application/src/main/data/json/system/scada_symbols/top-flow-meter.svg index f9bf64210f..bac39d98dc 100644 --- a/application/src/main/data/json/system/scada_symbols/top-flow-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/top-flow-meter.svg @@ -51,6 +51,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "value", "stateRenderFunction": "var value = ctx.values.value;\nctx.api.text(element, value.toFixed(0));\n", @@ -78,13 +83,32 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 0, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_TIME_SERIES", + "defaultValue": 0, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "flowRate" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -93,13 +117,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -108,13 +152,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -123,13 +187,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "broken", @@ -138,13 +222,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.broken}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "displayClick", @@ -153,13 +257,16 @@ "group": "{i18n:scada.symbol.display}", "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } }, { "id": "fluid", @@ -168,13 +275,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", @@ -183,13 +310,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", @@ -198,13 +345,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", @@ -213,13 +380,32 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", @@ -228,13 +414,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -509,9 +715,26 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] -}]]> +}]]> + diff --git a/application/src/main/data/json/system/scada_symbols/top-right-elbow-pipe.svg b/application/src/main/data/json/system/scada_symbols/top-right-elbow-pipe.svg index 9513ee7fc2..5537c23bb6 100644 --- a/application/src/main/data/json/system/scada_symbols/top-right-elbow-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/top-right-elbow-pipe.svg @@ -29,6 +29,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "vertical-fluid", "stateRenderFunction": "var fluid = ctx.values.fluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}\n", @@ -40,71 +45,175 @@ "id": "fluid", "name": "{i18n:scada.symbol.fluid-presence}", "hint": "{i18n:scada.symbol.fluid-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", "name": "{i18n:scada.symbol.flow-presence}", "hint": "{i18n:scada.symbol.flow-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", "name": "{i18n:scada.symbol.flow-direction}", "hint": "{i18n:scada.symbol.flow-direction-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", "name": "{i18n:scada.symbol.flow-animation-speed}", "hint": "{i18n:scada.symbol.flow-animation-speed-hint}", + "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -123,19 +232,35 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + - + diff --git a/application/src/main/data/json/system/scada_symbols/top-tee-pipe.svg b/application/src/main/data/json/system/scada_symbols/top-tee-pipe.svg index f14bc5e6c0..1dfa27e706 100644 --- a/application/src/main/data/json/system/scada_symbols/top-tee-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/top-tee-pipe.svg @@ -30,6 +30,11 @@ "stateRenderFunction": "var fluid = (ctx.values.leftFluid || ctx.values.rightFluid ||\n ctx.values.topFluid) && !ctx.values.leak;\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "right-fluid", "stateRenderFunction": "var fluid = ctx.values.rightFluid && !ctx.values.leak;\n\nif (fluid) {\n element.show();\n} else {\n element.hide();\n}", @@ -59,13 +64,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlow", @@ -74,13 +99,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlowDirection", @@ -89,13 +134,33 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leftFlowAnimationSpeed", @@ -104,13 +169,32 @@ "group": "{i18n:scada.symbol.left-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFluid", @@ -119,13 +203,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlow", @@ -134,13 +238,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlowDirection", @@ -149,13 +273,33 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "rightFlowAnimationSpeed", @@ -164,13 +308,32 @@ "group": "{i18n:scada.symbol.right-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFluid", @@ -179,13 +342,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlow", @@ -194,13 +377,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlowDirection", @@ -209,13 +412,33 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "topFlowAnimationSpeed", @@ -224,27 +447,67 @@ "group": "{i18n:scada.symbol.top-pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -295,13 +558,29 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] }]]> - + - + diff --git a/application/src/main/data/json/system/scada_symbols/vertical-ball-valve.svg b/application/src/main/data/json/system/scada_symbols/vertical-ball-valve.svg index 9aa3fcdefa..3aee266486 100644 --- a/application/src/main/data/json/system/scada_symbols/vertical-ball-valve.svg +++ b/application/src/main/data/json/system/scada_symbols/vertical-ball-valve.svg @@ -37,13 +37,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.opened}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "open", @@ -52,13 +72,32 @@ "group": null, "type": "action", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": true, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": { + "action": "SET_ATTRIBUTE", + "executeRpc": { + "method": "setState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "setAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "putTimeSeries": { + "key": "state" + }, + "valueToData": { + "type": "CONSTANT", + "constantValue": false, + "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" + } + }, + "defaultWidgetActionSettings": null }, { "id": "close", @@ -67,13 +106,32 @@ "group": null, "type": "action", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": { + "action": "SET_ATTRIBUTE", + "executeRpc": { + "method": "setState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "setAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "putTimeSeries": { + "key": "state" + }, + "valueToData": { + "type": "CONSTANT", + "constantValue": true, + "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" + } + }, + "defaultWidgetActionSettings": null } ], "properties": [ diff --git a/application/src/main/data/json/system/scada_symbols/vertical-inline-flow-meter.svg b/application/src/main/data/json/system/scada_symbols/vertical-inline-flow-meter.svg index 45b8d1ef2c..1c22c8d117 100644 --- a/application/src/main/data/json/system/scada_symbols/vertical-inline-flow-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/vertical-inline-flow-meter.svg @@ -1,4 +1,5 @@ -{ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="400" fill="none" version="1.1" viewBox="0 0 200 400"> +<tb:metadata xmlns=""><![CDATA[{ "title": "Vertical inline flow meter", "description": "Vertical inline flow meter component used to display flow related value and render various states. Includes pipe fluid and leak visualizations.", "searchTags": [ @@ -50,6 +51,11 @@ "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null + }, { "tag": "value", "stateRenderFunction": "var value = ctx.values.value;\nctx.api.text(element, value.toFixed(0));\n", @@ -77,13 +83,32 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 0, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_TIME_SERIES", + "defaultValue": 0, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "flowRate" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "warning", @@ -92,13 +117,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.warning}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "critical", @@ -107,13 +152,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.critical}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "criticalAnimation", @@ -122,13 +187,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.animation}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "broken", @@ -137,13 +222,33 @@ "group": "{i18n:scada.symbol.display}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.broken}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "displayClick", @@ -152,13 +257,16 @@ "group": "{i18n:scada.symbol.display}", "type": "widgetAction", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "openInSeparateDialog": false, + "openInPopover": false + } }, { "id": "fluid", @@ -167,13 +275,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", @@ -182,13 +310,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", @@ -197,13 +345,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", @@ -212,13 +380,32 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", @@ -227,13 +414,33 @@ "group": "{i18n:scada.symbol.pipe}", "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -508,10 +715,26 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] } - + diff --git a/application/src/main/data/json/system/scada_symbols/vertical-pipe.svg b/application/src/main/data/json/system/scada_symbols/vertical-pipe.svg index a836a47394..18ea6837e0 100644 --- a/application/src/main/data/json/system/scada_symbols/vertical-pipe.svg +++ b/application/src/main/data/json/system/scada_symbols/vertical-pipe.svg @@ -23,6 +23,11 @@ "tag": "leak", "stateRenderFunction": "var leak = ctx.values.leak;\nif (leak) {\n element.show();\n} else {\n element.hide();\n}", "actions": null + }, + { + "tag": "pipe-background", + "stateRenderFunction": "var color = ctx.properties.pipeColor;\nelement.attr({fill: color});", + "actions": null } ], "behavior": [ @@ -30,71 +35,175 @@ "id": "fluid", "name": "{i18n:scada.symbol.fluid-presence}", "hint": "{i18n:scada.symbol.fluid-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.fluid-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flow", "name": "{i18n:scada.symbol.flow-presence}", "hint": "{i18n:scada.symbol.flow-presence-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": "{i18n:scada.symbol.present}", "falseLabel": "{i18n:scada.symbol.absent}", "stateLabel": "{i18n:scada.symbol.flow-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowDirection", "name": "{i18n:scada.symbol.flow-direction}", "hint": "{i18n:scada.symbol.flow-direction-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": true, "trueLabel": "{i18n:scada.symbol.forward}", "falseLabel": "{i18n:scada.symbol.reverse}", "stateLabel": "{i18n:scada.symbol.forward}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": true, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "flowAnimationSpeed", "name": "{i18n:scada.symbol.flow-animation-speed}", "hint": "{i18n:scada.symbol.flow-animation-speed-hint}", + "group": null, "type": "value", "valueType": "DOUBLE", - "defaultValue": 1, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": 1, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "leak", "name": "{i18n:scada.symbol.leak}", "hint": "{i18n:scada.symbol.leak-hint}", + "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.leak-present}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -113,9 +222,26 @@ "min": null, "max": null, "step": null + }, + { + "id": "pipeColor", + "name": "{i18n:scada.symbol.pipe-color}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null } ] -}]]> +}]]> + diff --git a/application/src/main/data/json/system/scada_symbols/vertical-tank-with-level.svg b/application/src/main/data/json/system/scada_symbols/vertical-tank-with-level.svg deleted file mode 100644 index 06951fb94e..0000000000 --- a/application/src/main/data/json/system/scada_symbols/vertical-tank-with-level.svg +++ /dev/null @@ -1,24 +0,0 @@ - -{ - "title": "Vertical tank with level", - "widgetSizeX": 3, - "widgetSizeY": 5, - "tags": [], - "behavior": [], - "properties": [] -} - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/vertical-tank.svg b/application/src/main/data/json/system/scada_symbols/vertical-tank.svg new file mode 100644 index 0000000000..57d4d1978a --- /dev/null +++ b/application/src/main/data/json/system/scada_symbols/vertical-tank.svg @@ -0,0 +1,1394 @@ + +{ + "title": "Vertical tank", + "description": "Vertical tank with current volume value and level visualizations.", + "searchTags": [ + "tank" + ], + "widgetSizeX": 3, + "widgetSizeY": 5, + "tags": [ + { + "tag": "background", + "stateRenderFunction": "var color = ctx.properties.tankColor;\nelement.attr({fill: color});", + "actions": null + }, + { + "tag": "clickArea", + "stateRenderFunction": null, + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'click');" + } + } + }, + { + "tag": "fluid", + "stateRenderFunction": "if (!ctx.properties.scale) {\n element.hide();\n} else {\n var liquidPattern = ctx.svg.defs().findOne('pattern#liquid');\n if (liquidPattern) {\n liquidPattern.id(ctx.api.generateElementId());\n element.fill(liquidPattern);\n } else {\n liquidPattern = element.reference('fill');\n }\n\n var valueSet = element.remember('valueSet');\n if (!valueSet) {\n element.remember('valueSet', true);\n element.attr({height: 0});\n liquidPattern.transform({translateY: 590});\n }\n\n var currentVolume = ctx.values.currentVolume; \n var tankCapacity = ctx.values.tankCapacity; \n\n var height = currentVolume / tankCapacity;\n height = Math.max(0, Math.min(1, height))*765; \n \n var elementHeight = element.remember('height');\n if (height !== elementHeight) {\n element.remember('height', height);\n ctx.api.animate(element, 500).attr({height: height});\n liquidPattern.animate(500)\n .transform({ translateY: 590 + height });\n }\n}\n", + "actions": null + }, + { + "tag": "fluid-background", + "stateRenderFunction": "if (!ctx.properties.scale) {\n element.hide();\n} else {\n var color = ctx.properties.fluidColor;\n element.attr({fill: color, 'fill-opacity': 1});\n \n var valueSet = element.remember('valueSet');\n if (!valueSet) {\n element.remember('valueSet', true);\n element.attr({height: 0});\n }\n \n var currentVolume = ctx.values.currentVolume; \n var tankCapacity = ctx.values.tankCapacity; \n\n var height = currentVolume / tankCapacity;\n height = Math.max(0, Math.min(1, height))*765; \n \n var elementHeight = element.remember('height');\n if (height !== elementHeight) {\n element.remember('height', height);\n ctx.api.animate(element, 500).attr({height: height});\n }\n}\n", + "actions": null + }, + { + "tag": "scale", + "stateRenderFunction": "if (!ctx.properties.scale) {\n element.hide();\n} else {\n var scaleSet = element.remember('scaleSet');\n if (!scaleSet) {\n element.remember('scaleSet', true);\n element.clear();\n \n var majorIntervals = ctx.properties.majorIntervals;\n var minorIntervals = ctx.properties.minorIntervals;\n \n var start = 205;\n var majorIntervalLength = 760 / majorIntervals;\n var minorIntervalLength = majorIntervalLength / minorIntervals;\n for (var i = 0; i < majorIntervals + 1; i++) {\n var y = start + i * majorIntervalLength;\n var line = ctx.svg.line(340, y, 372, y).stroke({ width: 3 }).attr({class: 'majorTick'});\n element.add(line);\n var majorText = (100 - i * (100/majorIntervals)).toFixed(0);\n var majorTickText = ctx.svg.text(majorText);\n majorTickText.attr({x: 330, y: y + 2, 'text-anchor': 'end', 'dominant-baseline': 'middle', class: 'majorTickText'});\n element.add(majorTickText);\n if (i < majorIntervals) {\n drawMinorTicks(y, minorIntervals, minorIntervalLength);\n }\n }\n }\n \n var majorFont = ctx.properties.majorFont;\n var majorColor = ctx.properties.majorColor;\n var minorColor = ctx.properties.minorColor;\n if (ctx.values.critical) {\n majorColor = ctx.properties.majorCriticalColor;\n minorColor = ctx.properties.minorCriticalColor;\n } else if (ctx.values.warning) {\n majorColor = ctx.properties.minorWarningColor;\n minorColor = ctx.properties.minorWarningColor;\n }\n \n var majorTicks = element.find('line.majorTick');\n majorTicks.forEach(t => t.attr({stroke: majorColor}));\n \n var majorTicksText = element.find('text.majorTickText');\n ctx.api.font(majorTicksText, majorFont, majorColor);\n \n var minorTicks = element.find('line.minorTick');\n minorTicks.forEach(t => t.attr({stroke: minorColor}));\n \n var elementCriticalAnimation = element.remember('criticalAnimation');\n var criticalAnimation = ctx.values.critical && ctx.values.criticalAnimation;\n\n if (elementCriticalAnimation !== criticalAnimation) {\n element.remember('criticalAnimation', criticalAnimation);\n if (criticalAnimation) {\n ctx.api.animate(element, 500).attr({opacity: 0.15}).loop(0, true);\n } else {\n ctx.api.resetAnimation(element);\n }\n }\n}\n\nfunction drawMinorTicks(start, minorIntervals, minorIntervalLength) {\n for (var i = 1; i < minorIntervals; i++) {\n var minorY = start + i * minorIntervalLength;\n var minorLine = ctx.svg.line(352, minorY, 372, minorY).stroke({ width: 3 }).attr({class: 'minorTick'});\n element.add(minorLine);\n }\n}", + "actions": null + }, + { + "tag": "scale-background", + "stateRenderFunction": "if (!ctx.properties.scale) {\n element.hide();\n}", + "actions": null + }, + { + "tag": "top-layer", + "stateRenderFunction": "if (ctx.properties.transparent || !ctx.properties.scale) {\n element.hide();\n}", + "actions": null + }, + { + "tag": "value-box", + "stateRenderFunction": "if (!ctx.properties.valueBox) {\n element.hide();\n}", + "actions": null + }, + { + "tag": "value-box-background", + "stateRenderFunction": "if (ctx.properties.valueBox) {\n var color = ctx.properties.valueBoxColor;\n element.attr({fill: color});\n}", + "actions": null + }, + { + "tag": "value-text", + "stateRenderFunction": "if (ctx.properties.valueBox) {\n var valueTextFont = ctx.properties.valueTextFont;\n var valueTextColor = ctx.properties.valueTextColor;\n var currentVolume = ctx.values.currentVolume;\n var valueText = ctx.api.formatValue(currentVolume, 0, ctx.properties.valueUnits, false);\n ctx.api.font(element, valueTextFont, valueTextColor);\n ctx.api.text(element, valueText);\n}", + "actions": null + } + ], + "behavior": [ + { + "id": "tankCapacity", + "name": "{i18n:scada.symbol.tank-capacity}", + "hint": "{i18n:scada.symbol.tank-capacity-hint}", + "group": null, + "type": "value", + "valueType": "DOUBLE", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": null, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SERVER_SCOPE", + "key": "tankCapacity" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + }, + { + "id": "currentVolume", + "name": "{i18n:scada.symbol.current-volume}", + "hint": "{i18n:scada.symbol.current-volume-hint}", + "group": null, + "type": "value", + "valueType": "DOUBLE", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": { + "action": "GET_TIME_SERIES", + "defaultValue": null, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": null, + "key": "state" + }, + "getTimeSeries": { + "key": "liquidVolume" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + }, + { + "id": "warning", + "name": "{i18n:scada.symbol.warning-state}", + "hint": "{i18n:scada.symbol.warning-state-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.warning}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + }, + { + "id": "critical", + "name": "{i18n:scada.symbol.critical-state}", + "hint": "{i18n:scada.symbol.critical-state-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.critical}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + }, + { + "id": "criticalAnimation", + "name": "{i18n:scada.symbol.critical-state-animation}", + "hint": "{i18n:scada.symbol.critical-state-animation-hint}", + "group": null, + "type": "value", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": "{i18n:scada.symbol.animation}", + "defaultGetValueSettings": { + "action": "DO_NOTHING", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "key": "state", + "scope": null + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null + }, + { + "id": "click", + "name": "{i18n:scada.symbol.on-click}", + "hint": "{i18n:scada.symbol.on-click-hint}", + "group": null, + "type": "widgetAction", + "valueType": "BOOLEAN", + "trueLabel": null, + "falseLabel": null, + "stateLabel": null, + "defaultGetValueSettings": null, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": { + "type": "doNothing", + "targetDashboardStateId": null, + "openRightLayout": false, + "setEntityId": false, + "stateEntityParamName": null + } + } + ], + "properties": [ + { + "id": "tankColor", + "name": "{i18n:scada.symbol.tank-color}", + "type": "color", + "default": "#E5E5E5", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "fluidColor", + "name": "{i18n:scada.symbol.fluid-color}", + "type": "color", + "default": "#1EC1F480", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "valueBox", + "name": "{i18n:scada.symbol.value-box}", + "type": "switch", + "default": true, + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "valueBoxColor", + "name": "{i18n:scada.symbol.value-box}", + "type": "color", + "default": "#FFFFFF", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "valueBox", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "valueUnits", + "name": "{i18n:scada.symbol.value-text}", + "type": "units", + "default": "gal", + "required": null, + "subLabel": "{i18n:scada.symbol.units}", + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "valueBox", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "valueTextFont", + "name": "{i18n:scada.symbol.value-text}", + "type": "font", + "default": { + "size": 36, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal" + }, + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "valueBox", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "valueTextColor", + "name": "{i18n:scada.symbol.value-text}", + "type": "color", + "default": "#0000008A", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "valueBox", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "scale", + "name": "{i18n:scada.symbol.scale}", + "type": "switch", + "default": true, + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": null, + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "transparent", + "name": "{i18n:scada.symbol.transparent-mode}", + "type": "switch", + "default": false, + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "majorIntervals", + "name": "{i18n:scada.symbol.major-ticks}", + "type": "number", + "default": 10, + "required": null, + "subLabel": "{i18n:scada.symbol.intervals}", + "divider": true, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": 1, + "max": null, + "step": 1 + }, + { + "id": "majorFont", + "name": "{i18n:scada.symbol.major-ticks}", + "type": "font", + "default": { + "size": 24, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal" + }, + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "majorColor", + "name": "{i18n:scada.symbol.major-ticks-color}", + "type": "color", + "default": "#00000061", + "required": null, + "subLabel": "{i18n:scada.symbol.normal}", + "divider": true, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "majorWarningColor", + "name": "{i18n:scada.symbol.major-ticks-color}", + "type": "color", + "default": "#FAA405", + "required": null, + "subLabel": "{i18n:scada.symbol.warning}", + "divider": true, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "majorCriticalColor", + "name": "{i18n:scada.symbol.major-ticks-color}", + "type": "color", + "default": "#D12730", + "required": null, + "subLabel": "{i18n:scada.symbol.critical}", + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "minorIntervals", + "name": "{i18n:scada.symbol.minor-ticks}", + "type": "number", + "default": 5, + "required": null, + "subLabel": "{i18n:scada.symbol.intervals}", + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": 1, + "max": null, + "step": null + }, + { + "id": "minorColor", + "name": "{i18n:scada.symbol.minor-ticks-color}", + "type": "color", + "default": "#0000001F", + "required": null, + "subLabel": "{i18n:scada.symbol.normal}", + "divider": true, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "minorWarningColor", + "name": "{i18n:scada.symbol.minor-ticks-color}", + "type": "color", + "default": "#FAA405", + "required": null, + "subLabel": "{i18n:scada.symbol.warning}", + "divider": true, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "minorCriticalColor", + "name": "{i18n:scada.symbol.minor-ticks-color}", + "type": "color", + "default": "#D12730", + "required": null, + "subLabel": "{i18n:scada.symbol.critical}", + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "scale", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + } + ] +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1660 gal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/vertical-wheel-valve.svg b/application/src/main/data/json/system/scada_symbols/vertical-wheel-valve.svg index e304b52f4f..d43083040f 100644 --- a/application/src/main/data/json/system/scada_symbols/vertical-wheel-valve.svg +++ b/application/src/main/data/json/system/scada_symbols/vertical-wheel-valve.svg @@ -1,5 +1,4 @@ - - { +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="400" fill="none" version="1.1" viewBox="0 0 200 400"><tb:metadata xmlns=""><![CDATA[{ "title": "Vertical wheel valve", "description": "Vertical wheel valve with open/close animation and state colors.", "searchTags": [ @@ -37,13 +36,33 @@ "group": null, "type": "value", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": "{i18n:scada.symbol.opened}", - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": { + "action": "GET_ATTRIBUTE", + "defaultValue": false, + "executeRpc": { + "method": "getState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "getAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "getTimeSeries": { + "key": "state" + }, + "dataToValue": { + "type": "NONE", + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true + } + }, + "defaultSetValueSettings": null, + "defaultWidgetActionSettings": null }, { "id": "open", @@ -52,13 +71,32 @@ "group": null, "type": "action", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": true, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": { + "action": "SET_ATTRIBUTE", + "executeRpc": { + "method": "setState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "setAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "putTimeSeries": { + "key": "state" + }, + "valueToData": { + "type": "CONSTANT", + "constantValue": true, + "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" + } + }, + "defaultWidgetActionSettings": null }, { "id": "close", @@ -67,13 +105,32 @@ "group": null, "type": "action", "valueType": "BOOLEAN", - "defaultValue": false, "trueLabel": null, "falseLabel": null, "stateLabel": null, - "valueToDataType": "CONSTANT", - "constantValue": false, - "valueToDataFunction": "" + "defaultGetValueSettings": null, + "defaultSetValueSettings": { + "action": "SET_ATTRIBUTE", + "executeRpc": { + "method": "setState", + "requestTimeout": 5000, + "requestPersistent": false, + "persistentPollingInterval": 1000 + }, + "setAttribute": { + "scope": "SHARED_SCOPE", + "key": "open" + }, + "putTimeSeries": { + "key": "state" + }, + "valueToData": { + "type": "CONSTANT", + "constantValue": false, + "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" + } + }, + "defaultWidgetActionSettings": null } ], "properties": [ @@ -143,16 +200,7 @@ } ] } - - - - - - - - - - + @@ -237,24 +285,16 @@ - - + - - + - - - + - - - - - + \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json b/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json index 306106c06a..224938c019 100644 --- a/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json +++ b/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json @@ -22,6 +22,12 @@ "bottom_tee_pipe", "right_tee_pipe", "top_tee_pipe", + "right_elbow_drain_pipe", + "left_elbow_drain_pipe", + "left_drain_pipe", + "right_drain_pipe", + "short_left_drain_pipe", + "short_right_drain_pipe", "top_flow_meter", "right_flow_meter", "bottom_flow_meter", @@ -41,8 +47,6 @@ "vertical_wheel_valve", "horizontal_ball_valve", "vertical_ball_valve", - "horizontal_tank_with_screen", - "vertical_tank_with_level", - "level_and_fan" + "vertical_tank" ] } \ No newline at end of file diff --git a/application/src/main/data/upgrade/3.7.0/schema_update.sql b/application/src/main/data/upgrade/3.7.0/schema_update.sql index 9ea7c5679f..51e78a504e 100644 --- a/application/src/main/data/upgrade/3.7.0/schema_update.sql +++ b/application/src/main/data/upgrade/3.7.0/schema_update.sql @@ -68,14 +68,34 @@ $$; CREATE SEQUENCE IF NOT EXISTS attribute_kv_version_seq cache 1; CREATE SEQUENCE IF NOT EXISTS ts_kv_latest_version_seq cache 1; -ALTER TABLE attribute_kv ADD COLUMN version bigint default 0; -ALTER TABLE ts_kv_latest ADD COLUMN version bigint default 0; +ALTER TABLE attribute_kv ADD COLUMN IF NOT EXISTS version bigint default 0; +ALTER TABLE ts_kv_latest ADD COLUMN IF NOT EXISTS version bigint default 0; -- KV VERSIONING UPDATE END -- RELATION VERSIONING UPDATE START CREATE SEQUENCE IF NOT EXISTS relation_version_seq cache 1; -ALTER TABLE relation ADD COLUMN version bigint default 0; +ALTER TABLE relation ADD COLUMN IF NOT EXISTS version bigint default 0; -- RELATION VERSIONING UPDATE END + + +-- ENTITIES VERSIONING UPDATE START + +ALTER TABLE device ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE device_profile ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE device_credentials ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE asset ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE asset_profile ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE entity_view ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE tb_user ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE customer ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE edge ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE rule_chain ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE dashboard ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE widget_type ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE widgets_bundle ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; +ALTER TABLE tenant ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; + +-- ENTITIES VERSIONING UPDATE END diff --git a/application/src/main/java/org/springframework/http/converter/xml/MappingJackson2XmlHttpMessageConverter.java b/application/src/main/java/org/springframework/http/converter/xml/MappingJackson2XmlHttpMessageConverter.java new file mode 100644 index 0000000000..158f29a03a --- /dev/null +++ b/application/src/main/java/org/springframework/http/converter/xml/MappingJackson2XmlHttpMessageConverter.java @@ -0,0 +1,68 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.springframework.http.converter.xml; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.util.Assert; + +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; + +/** + * RestTemplate firstly uses MappingJackson2XmlHttpMessageConverter converter instead of MappingJackson2HttpMessageConverter. + * It produces error UnsupportedMediaType, so this converter had to be shadowed for read and write operations to use the correct converter + */ +public class MappingJackson2XmlHttpMessageConverter extends AbstractJackson2HttpMessageConverter { + private static final List problemDetailMediaTypes; + + public MappingJackson2XmlHttpMessageConverter() { + this(Jackson2ObjectMapperBuilder.xml().build()); + } + + public MappingJackson2XmlHttpMessageConverter(ObjectMapper objectMapper) { + super(objectMapper, new MediaType[]{new MediaType("application", "xml", StandardCharsets.UTF_8), new MediaType("text", "xml", StandardCharsets.UTF_8), new MediaType("application", "*+xml", StandardCharsets.UTF_8)}); + Assert.isInstanceOf(XmlMapper.class, objectMapper, "XmlMapper required"); + } + + public void setObjectMapper(ObjectMapper objectMapper) { + Assert.isInstanceOf(XmlMapper.class, objectMapper, "XmlMapper required"); + super.setObjectMapper(objectMapper); + } + + protected List getMediaTypesForProblemDetail() { + return problemDetailMediaTypes; + } + + static { + problemDetailMediaTypes = Collections.singletonList(MediaType.APPLICATION_PROBLEM_XML); + } + + @Override + public boolean canRead(Type type, Class contextClass, MediaType mediaType) { + return false; + } + + @Override + public boolean canWrite(Class clazz, MediaType mediaType) { + return false; + } +} diff --git a/application/src/main/java/org/thingsboard/server/actors/shared/ComponentMsgProcessor.java b/application/src/main/java/org/thingsboard/server/actors/shared/ComponentMsgProcessor.java index 86e9fc6982..298874cc51 100644 --- a/application/src/main/java/org/thingsboard/server/actors/shared/ComponentMsgProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/shared/ComponentMsgProcessor.java @@ -78,7 +78,7 @@ public abstract class ComponentMsgProcessor extends Abstract } public void scheduleStatsPersistTick(TbActorCtx context, long statsPersistFrequency) { - schedulePeriodicMsgWithDelay(context, new StatsPersistTick(), statsPersistFrequency, statsPersistFrequency); + schedulePeriodicMsgWithDelay(context, StatsPersistTick.INSTANCE, statsPersistFrequency, statsPersistFrequency); } protected boolean checkMsgValid(TbMsg tbMsg) { diff --git a/application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistTick.java b/application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistTick.java index 541da7494f..25271262b5 100644 --- a/application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistTick.java +++ b/application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistTick.java @@ -18,7 +18,9 @@ package org.thingsboard.server.actors.stats; import org.thingsboard.server.common.msg.MsgType; import org.thingsboard.server.common.msg.TbActorMsg; -public final class StatsPersistTick implements TbActorMsg { +public enum StatsPersistTick implements TbActorMsg { + INSTANCE; + @Override public MsgType getMsgType() { return MsgType.STATS_PERSIST_TICK_MSG; 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 b723603e8a..29b9db10ab 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -65,6 +65,7 @@ import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeInfo; +import org.thingsboard.server.common.data.exception.EntityVersionMismatchException; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.AlarmCommentId; @@ -390,6 +391,8 @@ public abstract class BaseController { } else { return new ThingsboardException("Database error", ThingsboardErrorCode.GENERAL); } + } else if (exception instanceof EntityVersionMismatchException) { + return new ThingsboardException(exception.getMessage(), exception, ThingsboardErrorCode.VERSION_CONFLICT); } return new ThingsboardException(exception.getMessage(), exception, ThingsboardErrorCode.GENERAL); } 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 41a2acdecf..4d83d4debb 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java +++ b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java @@ -793,7 +793,7 @@ public class ControllerConstants { " * 'SHARED_ATTRIBUTE' - used for shared attributes; \n" + " * 'SERVER_ATTRIBUTE' - used for server attributes; \n" + " * 'ATTRIBUTE' - used for any of the above; \n" + - " * 'TIME_SERIES' - used for time-series values; \n" + + " * 'TIME_SERIES' - used for time series values; \n" + " * 'ENTITY_FIELD' - used for accessing entity fields like 'name', 'label', etc. The list of available fields depends on the entity type; \n" + " * 'ALARM_FIELD' - similar to entity field, but is used in alarm queries only; \n" + "\n\n Let's review the example:\n\n" + @@ -904,7 +904,7 @@ public class ControllerConstants { protected static final String KEY_FILTERS = "\n\n # Key Filters" + - "\nKey Filter allows you to define complex logical expressions over entity field, attribute or latest time-series value. The filter is defined using 'key', 'valueType' and 'predicate' objects. " + + "\nKey Filter allows you to define complex logical expressions over entity field, attribute or latest time series value. The filter is defined using 'key', 'valueType' and 'predicate' objects. " + "Single Entity Query may have zero, one or multiple predicates. If multiple filters are defined, they are evaluated using logical 'AND'. " + "The example below checks that temperature of the entity is above 20 degrees:" + "\n\n" + MARKDOWN_CODE_BLOCK_START + @@ -935,7 +935,7 @@ public class ControllerConstants { "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" + "\n\nOptional **key filters** allow to filter results of the entity filter by complex criteria against " + "main entity fields (name, label, type, etc), attributes and telemetry. " + - "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"." + + "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and time series field 'batteryLevel' > 40\"." + "\n\nLet's review the example:" + "\n\n" + MARKDOWN_CODE_BLOCK_START + "{\n" + @@ -970,13 +970,13 @@ public class ControllerConstants { protected static final String ENTITY_DATA_QUERY_DESCRIPTION = "Allows to run complex queries over platform entities (devices, assets, customers, etc) " + "based on the combination of main entity filter and multiple key filters. " + - "Returns the paginated result of the query that contains requested entity fields and latest values of requested attributes and time-series data.\n\n" + + "Returns the paginated result of the query that contains requested entity fields and latest values of requested attributes and time series data.\n\n" + "# Query Definition\n\n" + "\n\nMain **entity filter** is mandatory and defines generic search criteria. " + "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" + "\n\nOptional **key filters** allow to filter results of the **entity filter** by complex criteria against " + "main entity fields (name, label, type, etc), attributes and telemetry. " + - "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"." + + "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and time series field 'batteryLevel' > 40\"." + "\n\nThe **entity fields** and **latest values** contains list of entity fields and latest attribute/telemetry fields to fetch for each entity." + "\n\nThe **page link** contains information about the page to fetch and the sort ordering." + "\n\nLet's review the example:" + @@ -1054,7 +1054,7 @@ public class ControllerConstants { protected static final String ALARM_DATA_QUERY_DESCRIPTION = "This method description defines how Alarm Data Query extends the Entity Data Query. " + "See method 'Find Entity Data by Query' first to get the info about 'Entity Data Query'." + "\n\n The platform will first search the entities that match the entity and key filters. Then, the platform will use 'Alarm Page Link' to filter the alarms related to those entities. " + - "Finally, platform fetch the properties of alarm that are defined in the **'alarmFields'** and combine them with the other entity, attribute and latest time-series fields to return the result. " + + "Finally, platform fetch the properties of alarm that are defined in the **'alarmFields'** and combine them with the other entity, attribute and latest time series fields to return the result. " + "\n\n See example of the alarm query below. The query will search first 100 active alarms with type 'Temperature Alarm' or 'Fire Alarm' for any device with current temperature > 0. " + "The query will return combination of the entity fields: name of the device, device model and latest temperature reading and alarms fields: createdTime, type, severity and status: " + "\n\n" + MARKDOWN_CODE_BLOCK_START + @@ -1175,7 +1175,7 @@ public class ControllerConstants { protected static final String ALARM_FILTER_KEY = "## Alarm Filter Key" + NEW_LINE + "Filter Key defines either entity field, attribute, telemetry or constant. It is a JSON object that consists the key name and type. The following filter key types are supported:\n" + " * 'ATTRIBUTE' - used for attributes values;\n" + - " * 'TIME_SERIES' - used for time-series values;\n" + + " * 'TIME_SERIES' - used for time series values;\n" + " * 'ENTITY_FIELD' - used for accessing entity fields like 'name', 'label', etc. The list of available fields depends on the entity type;\n" + " * 'CONSTANT' - constant value specified." + NEW_LINE + "Let's review the example:" + NEW_LINE + MARKDOWN_CODE_BLOCK_START + @@ -1293,7 +1293,7 @@ public class ControllerConstants { protected static final String KEY_FILTERS_DESCRIPTION = "# Key Filters" + NEW_LINE + "Key filter objects are created under the **'condition'** array. They allow you to define complex logical expressions over entity field, " + - "attribute, latest time-series value or constant. The filter is defined using 'key', 'valueType', " + + "attribute, latest time series value or constant. The filter is defined using 'key', 'valueType', " + "'value' (refers to the value of the 'CONSTANT' alarm filter key type) and 'predicate' objects. Let's review each object:" + NEW_LINE + ALARM_FILTER_KEY + FILTER_VALUE_TYPE + NEW_LINE + DEVICE_PROFILE_FILTER_PREDICATE + NEW_LINE; @@ -1606,7 +1606,7 @@ public class ControllerConstants { 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."; - protected static final String TELEMETRY_KEYS_DESCRIPTION = TELEMETRY_KEYS_BASE_DESCRIPTION + " If keys are not selected, the result will return all latest timeseries. For example, 'temperature,humidity'."; + protected static final String TELEMETRY_KEYS_DESCRIPTION = TELEMETRY_KEYS_BASE_DESCRIPTION + " If keys are not selected, the result will return all latest time series. For example, 'temperature,humidity'."; protected static final String TELEMETRY_SCOPE_DESCRIPTION = "Value is deprecated, reserved for backward compatibility and not used in the API call implementation. Specify any scope for compatibility"; protected static final String TELEMETRY_JSON_REQUEST_DESCRIPTION = "A JSON with the telemetry values. See API call description for more details."; @@ -1622,11 +1622,11 @@ public class ControllerConstants { protected static final String SAVE_ENTITY_ATTRIBUTES_STATUS_UNAUTHORIZED = "User is not authorized to save entity attributes for selected entity. Most likely, User belongs to different Customer or Tenant."; protected static final String SAVE_ENTITY_ATTRIBUTES_STATUS_INTERNAL_SERVER_ERROR = "The exception was thrown during processing the request. " + "Platform creates an audit log event about entity attributes updates with action type 'ATTRIBUTES_UPDATED' that includes an error stacktrace."; - protected static final String SAVE_ENTITY_TIMESERIES_STATUS_OK = "Timeseries from the request was created or updated. " + - "Platform creates an audit log event about entity timeseries updates with action type 'TIMESERIES_UPDATED'."; - protected static final String SAVE_ENTITY_TIMESERIES_STATUS_UNAUTHORIZED = "User is not authorized to save entity timeseries for selected entity. Most likely, User belongs to different Customer or Tenant."; + protected static final String SAVE_ENTITY_TIMESERIES_STATUS_OK = "Time series from the request was created or updated. " + + "Platform creates an audit log event about entity time series updates with action type 'TIMESERIES_UPDATED'."; + protected static final String SAVE_ENTITY_TIMESERIES_STATUS_UNAUTHORIZED = "User is not authorized to save entity time series for selected entity. Most likely, User belongs to different Customer or Tenant."; protected static final String SAVE_ENTITY_TIMESERIES_STATUS_INTERNAL_SERVER_ERROR = "The exception was thrown during processing the request. " + - "Platform creates an audit log event about entity timeseries updates with action type 'TIMESERIES_UPDATED' that includes an error stacktrace."; + "Platform creates an audit log event about entity time series updates with action type 'TIMESERIES_UPDATED' that includes an error stacktrace."; protected static final String ENTITY_ATTRIBUTE_SCOPES_TEMPLATE = " List of possible attribute scopes depends on the entity type: " + "\n\n * SERVER_SCOPE - supported for all entity types;" + 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 54049a808e..e7915fc22c 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java @@ -125,8 +125,8 @@ public class DeviceProfileController extends BaseController { return checkNotNull(deviceProfileService.findDefaultDeviceProfileInfo(getTenantId())); } - @ApiOperation(value = "Get time-series keys (getTimeseriesKeys)", - notes = "Get a set of unique time-series keys used by devices that belong to specified profile. " + + @ApiOperation(value = "Get time series keys (getTimeseriesKeys)", + notes = "Get a set of unique time series keys used by devices that belong to specified profile. " + "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. " + 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 33b6045248..26c30f85d1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -490,7 +490,7 @@ public class EdgeController extends BaseController { if (fromEdgeSyncResponse.isSuccess()) { response.setResult(new ResponseEntity<>(HttpStatus.OK)); } else { - response.setErrorResult(new ThingsboardException("Edge is not connected", ThingsboardErrorCode.GENERAL)); + response.setErrorResult(new ThingsboardException(fromEdgeSyncResponse.getError(), ThingsboardErrorCode.GENERAL)); } } 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 6833a7ddfb..b1733a9af0 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -243,8 +243,8 @@ public class TelemetryController extends BaseController { (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. " + + @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) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/timeseries", method = RequestMethod.GET) @@ -256,10 +256,10 @@ public class TelemetryController extends BaseController { (result, tenantId, entityId) -> Futures.addCallback(tsService.findAllLatest(tenantId, entityId), getTsKeysToResponseCallback(result), MoreExecutors.directExecutor())); } - @ApiOperation(value = "Get latest time-series value (getLatestTimeseries)", - notes = "Returns all time-series that belong to specified entity. Use optional 'keys' parameter to return specific time-series." + + @ApiOperation(value = "Get latest time series value (getLatestTimeseries)", + notes = "Returns all time series that belong to specified entity. Use optional 'keys' parameter to return specific time series." + " The result is a JSON object. The format of the values depends on the 'useStrictDataTypes' parameter." + - " By default, all time-series values are converted to strings: \n\n" + " By default, all time series values are converted to strings: \n\n" + MARKDOWN_CODE_BLOCK_START + LATEST_TS_NON_STRICT_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END @@ -282,8 +282,8 @@ public class TelemetryController extends BaseController { (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictDataTypes)); } - @ApiOperation(value = "Get time-series data (getTimeseries)", - notes = "Returns a range of time-series values for specified entity. " + + @ApiOperation(value = "Get time series data (getTimeseries)", + notes = "Returns a range of time series values for specified entity. " + "Returns not aggregated data by default. " + "Use aggregation function ('agg') and aggregation interval ('interval') to enable aggregation of the results on the database / server side. " + "The aggregation is generally more efficient then fetching all records. \n\n" @@ -308,7 +308,7 @@ public class TelemetryController extends BaseController { @RequestParam(name = "interval", defaultValue = "0") Long interval, @Parameter(description = "A string value representing the timezone that will be used to calculate exact timestamps for 'WEEK', 'WEEK_ISO', 'MONTH' and 'QUARTER' interval types.") @RequestParam(name = "timeZone", required = false) String timeZone, - @Parameter(description = "An integer value that represents a max number of timeseries data points to fetch." + + @Parameter(description = "An integer value that represents a max number of time series 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, @Parameter(description = "A string value representing the aggregation function. " + @@ -406,8 +406,8 @@ public class TelemetryController extends BaseController { } - @ApiOperation(value = "Save or update time-series data (saveEntityTelemetry)", - notes = "Creates or updates the entity time-series data based on the Entity Id and request payload." + + @ApiOperation(value = "Save or update time series data (saveEntityTelemetry)", + 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) @@ -429,8 +429,8 @@ public class TelemetryController extends BaseController { return saveTelemetry(getTenantId(), entityId, requestBody, 0L); } - @ApiOperation(value = "Save or update time-series data with TTL (saveEntityTelemetryWithTTL)", - notes = "Creates or updates the entity time-series data based on the Entity Id and request payload." + + @ApiOperation(value = "Save or update time series data with TTL (saveEntityTelemetryWithTTL)", + 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. " + "\n\nThe ttl parameter takes affect only in case of Cassandra DB." @@ -454,21 +454,21 @@ public class TelemetryController extends BaseController { return saveTelemetry(getTenantId(), entityId, requestBody, ttl); } - @ApiOperation(value = "Delete entity time-series data (deleteEntityTimeseries)", - notes = "Delete time-series for selected entity based on entity id, entity type and keys." + - " Use 'deleteAllDataForKeys' to delete all time-series data." + + @ApiOperation(value = "Delete entity time series data (deleteEntityTimeseries)", + notes = "Delete time series for selected entity based on entity id, entity type and keys." + + " Use 'deleteAllDataForKeys' to delete all time series data." + " Use 'startTs' and 'endTs' to specify time-range instead. " + " 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. " + + " 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) @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'."), + @ApiResponse(responseCode = "200", description = "Time series for the selected keys in the request was removed. " + + "Platform creates an audit log event about entity time series removal with action type 'TIMESERIES_DELETED'."), @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 = "401", description = "User is not authorized to delete entity time series 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."), + "Platform creates an audit log event about entity time series 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) @@ -649,12 +649,12 @@ public class TelemetryController extends BaseController { try { telemetryJson = JsonParser.parseString(requestBody); } catch (Exception e) { - return getImmediateDeferredResult("Unable to parse timeseries payload: Invalid JSON body!", HttpStatus.BAD_REQUEST); + return getImmediateDeferredResult("Unable to parse time series payload: Invalid JSON body!", HttpStatus.BAD_REQUEST); } try { telemetryRequest = JsonConverter.convertToTelemetry(telemetryJson, System.currentTimeMillis()); } catch (Exception e) { - return getImmediateDeferredResult("Unable to parse timeseries payload. Invalid JSON body: " + e.getMessage(), HttpStatus.BAD_REQUEST); + return getImmediateDeferredResult("Unable to parse time series payload. Invalid JSON body: " + e.getMessage(), HttpStatus.BAD_REQUEST); } List entries = new ArrayList<>(); for (Map.Entry> entry : telemetryRequest.entrySet()) { @@ -663,7 +663,7 @@ public class TelemetryController extends BaseController { } } if (entries.isEmpty()) { - return getImmediateDeferredResult("No timeseries data found in request body!", HttpStatus.BAD_REQUEST); + return getImmediateDeferredResult("No time series data found in request body!", HttpStatus.BAD_REQUEST); } SecurityUser user = getCurrentUser(); return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_TELEMETRY, entityIdSrc, (result, tenantId, entityId) -> { 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 fd73a424a3..256302f30e 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -92,6 +92,7 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand errorCodeToStatusMap.put(ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS); errorCodeToStatusMap.put(ThingsboardErrorCode.TOO_MANY_UPDATES, HttpStatus.TOO_MANY_REQUESTS); errorCodeToStatusMap.put(ThingsboardErrorCode.SUBSCRIPTION_VIOLATION, HttpStatus.FORBIDDEN); + errorCodeToStatusMap.put(ThingsboardErrorCode.VERSION_CONFLICT, HttpStatus.CONFLICT); } private static ThingsboardErrorCode statusToErrorCode(HttpStatus status) { 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 3de4c95cc3..0eb128d0b7 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 @@ -182,7 +182,8 @@ public class EdgeEventSourcingListener { return false; } if (oldEntity != null) { - User oldUser = (User) oldEntity; + user = JacksonUtil.clone(user); + User oldUser = JacksonUtil.clone((User) oldEntity); cleanUpUserAdditionalInfo(oldUser); cleanUpUserAdditionalInfo(user); return !user.equals(oldUser); @@ -226,6 +227,7 @@ public class EdgeEventSourcingListener { user.setAdditionalInfo(additionalInfo); } } + user.setVersion(null); } private EdgeEventType getEdgeEventTypeForEntityEvent(Object entity) { 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 04e6fe2185..46bf3f69a4 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 @@ -287,22 +287,31 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i private void startSyncProcess(TenantId tenantId, EdgeId edgeId, UUID requestId) { EdgeGrpcSession session = sessions.get(edgeId); if (session != null) { - boolean success = false; - if (session.isConnected()) { - session.startSyncProcess(true); - success = true; + if (!session.isSyncCompleted()) { + clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, false, "Sync process is active at the moment")); + } else { + boolean success = false; + if (session.isConnected()) { + session.startSyncProcess(true); + success = true; + } + clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, success, "")); } - clusterService.pushEdgeSyncResponseToCore(new FromEdgeSyncResponse(requestId, tenantId, edgeId, success)); } } @Override public void processSyncRequest(ToEdgeSyncRequest request, Consumer responseConsumer) { - log.trace("[{}][{}] Processing sync edge request [{}]", request.getTenantId(), request.getId(), request.getEdgeId()); UUID requestId = request.getId(); - localSyncEdgeRequests.put(requestId, responseConsumer); - clusterService.pushEdgeSyncRequestToCore(request); - scheduleSyncRequestTimeout(request, requestId); + EdgeGrpcSession session = sessions.get(request.getEdgeId()); + if (session != null && !session.isSyncCompleted()) { + responseConsumer.accept(new FromEdgeSyncResponse(requestId, request.getTenantId(), request.getEdgeId(), false, "Sync process is active at the moment")); + } else { + log.trace("[{}][{}] Processing sync edge request [{}]", request.getTenantId(), request.getId(), request.getEdgeId()); + localSyncEdgeRequests.put(requestId, responseConsumer); + clusterService.pushEdgeSyncRequestToCore(request); + scheduleSyncRequestTimeout(request, requestId); + } } private void scheduleSyncRequestTimeout(ToEdgeSyncRequest request, UUID requestId) { @@ -312,7 +321,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i Consumer consumer = localSyncEdgeRequests.remove(requestId); if (consumer != null) { log.trace("[{}] timeout for processing sync edge request.", requestId); - consumer.accept(new FromEdgeSyncResponse(requestId, request.getTenantId(), request.getEdgeId(), false)); + consumer.accept(new FromEdgeSyncResponse(requestId, request.getTenantId(), request.getEdgeId(), false, "Edge is not connected")); } }, 20, TimeUnit.SECONDS); } 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 81f90fee51..97b28c083f 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 @@ -247,6 +247,7 @@ public final class EdgeGrpcSession implements Closeable { } }, ctx.getGrpcCallbackExecutorService()); } else { + log.info("[{}][{}] sync process completed", this.tenantId, edge.getId()); DownlinkMsg syncCompleteDownlinkMsg = DownlinkMsg.newBuilder() .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) .setSyncCompletedMsg(SyncCompletedMsg.newBuilder().build()) @@ -325,7 +326,11 @@ public final class EdgeGrpcSession implements Closeable { } private void sendDownlinkMsg(ResponseMsg downlinkMsg) { - log.trace("[{}][{}] Sending downlink msg [{}]", this.tenantId, this.sessionId, downlinkMsg); + if (downlinkMsg.getDownlinkMsg().getWidgetTypeUpdateMsgCount() > 0) { + log.trace("[{}][{}] Sending downlink widgetTypeUpdateMsg, downlinkMsgId = {}", this.tenantId, this.sessionId, downlinkMsg.getDownlinkMsg().getDownlinkMsgId()); + } else { + log.trace("[{}][{}] Sending downlink msg [{}]", this.tenantId, this.sessionId, downlinkMsg); + } if (isConnected()) { downlinkMsgLock.lock(); try { @@ -337,7 +342,7 @@ public final class EdgeGrpcSession implements Closeable { } finally { downlinkMsgLock.unlock(); } - log.trace("[{}][{}] Response msg successfully sent [{}]", this.tenantId, this.sessionId, downlinkMsg); + log.trace("[{}][{}] Response msg successfully sent. downlinkMsgId = {}", this.tenantId, this.sessionId, downlinkMsg.getDownlinkMsg().getDownlinkMsgId()); } } @@ -551,9 +556,13 @@ public final class EdgeGrpcSession implements Closeable { DownlinkMsg downlinkMsg = null; try { switch (edgeEvent.getAction()) { - case UPDATED, ADDED, DELETED, ASSIGNED_TO_EDGE, UNASSIGNED_FROM_EDGE, ALARM_ACK, ALARM_CLEAR, ALARM_DELETE, CREDENTIALS_UPDATED, RELATION_ADD_OR_UPDATE, RELATION_DELETED, CREDENTIALS_REQUEST, RPC_CALL, ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER, ADDED_COMMENT, UPDATED_COMMENT, DELETED_COMMENT -> { + case UPDATED, ADDED, DELETED, ASSIGNED_TO_EDGE, UNASSIGNED_FROM_EDGE, ALARM_ACK, ALARM_CLEAR, ALARM_DELETE, CREDENTIALS_UPDATED, RELATION_ADD_OR_UPDATE, RELATION_DELETED, RPC_CALL, ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER, ADDED_COMMENT, UPDATED_COMMENT, DELETED_COMMENT -> { downlinkMsg = convertEntityEventToDownlink(edgeEvent); - log.trace("[{}][{}] entity message processed [{}]", this.tenantId, this.sessionId, downlinkMsg); + if (downlinkMsg != null && downlinkMsg.getWidgetTypeUpdateMsgCount() > 0) { + log.trace("[{}][{}] widgetTypeUpdateMsg message processed, downlinkMsgId = {}", this.tenantId, this.sessionId, downlinkMsg.getDownlinkMsgId()); + } else { + log.trace("[{}][{}] entity message processed [{}]", this.tenantId, this.sessionId, downlinkMsg); + } } case ATTRIBUTES_UPDATED, POST_ATTRIBUTES, ATTRIBUTES_DELETED, TIMESERIES_UPDATED -> downlinkMsg = ctx.getTelemetryProcessor().convertTelemetryEventToDownlink(edge, edgeEvent); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java index 6321991586..125fd48463 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.service.edge.rpc; +import lombok.Getter; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.EntityId; @@ -53,6 +54,7 @@ public class EdgeSyncCursor { private final List fetchers = new LinkedList<>(); + @Getter private int currentIdx = 0; public EdgeSyncCursor(EdgeContextComponent ctx, Edge edge, boolean fullSync) { @@ -62,12 +64,12 @@ public class EdgeSyncCursor { fetchers.add(new RuleChainsEdgeEventFetcher(ctx.getRuleChainService())); fetchers.add(new AdminSettingsEdgeEventFetcher(ctx.getAdminSettingsService())); fetchers.add(new TenantAdminUsersEdgeEventFetcher(ctx.getUserService())); - Customer publicCustomer = ctx.getCustomerService().findOrCreatePublicCustomer(edge.getTenantId()); - fetchers.add(new CustomerEdgeEventFetcher(publicCustomer.getId())); - if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { - fetchers.add(new CustomerEdgeEventFetcher(edge.getCustomerId())); - fetchers.add(new CustomerUsersEdgeEventFetcher(ctx.getUserService(), edge.getCustomerId())); - } + } + Customer publicCustomer = ctx.getCustomerService().findOrCreatePublicCustomer(edge.getTenantId()); + fetchers.add(new CustomerEdgeEventFetcher(publicCustomer.getId())); + if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { + fetchers.add(new CustomerEdgeEventFetcher(edge.getCustomerId())); + fetchers.add(new CustomerUsersEdgeEventFetcher(ctx.getUserService(), edge.getCustomerId())); } fetchers.add(new DashboardsEdgeEventFetcher(ctx.getDashboardService())); fetchers.add(new DefaultProfilesEdgeEventFetcher(ctx.getDeviceProfileService(), ctx.getAssetProfileService())); @@ -102,9 +104,4 @@ public class EdgeSyncCursor { currentIdx++; return edgeEventFetcher; } - - public int getCurrentIdx() { - return currentIdx; - } - } 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 f46c07ab5a..b1c1fc63c5 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 @@ -373,7 +373,7 @@ public abstract class BaseEdgeProcessor { private boolean doSaveIfEdgeIsOffline(EdgeEventType type, EdgeEventActionType action) { return switch (action) { - case TIMESERIES_UPDATED, ALARM_ACK, ALARM_CLEAR, ALARM_ASSIGNED, ALARM_UNASSIGNED, CREDENTIALS_REQUEST, ADDED_COMMENT, UPDATED_COMMENT -> + case TIMESERIES_UPDATED, ALARM_ACK, ALARM_CLEAR, ALARM_ASSIGNED, ALARM_UNASSIGNED, ADDED_COMMENT, UPDATED_COMMENT -> true; default -> switch (type) { case ALARM, ALARM_COMMENT, RULE_CHAIN, RULE_CHAIN_METADATA, USER, CUSTOMER, TENANT, TENANT_PROFILE, WIDGETS_BUNDLE, WIDGET_TYPE, diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java index 5e73034b1c..f448766994 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java @@ -43,7 +43,6 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponseActorMsg; import org.thingsboard.server.dao.exception.DataValidationException; -import org.thingsboard.server.gen.edge.v1.DeviceCredentialsRequestMsg; import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg; import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; @@ -70,7 +69,7 @@ public abstract class DeviceEdgeProcessor extends BaseDeviceProcessor implements case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE: saveOrUpdateDevice(tenantId, deviceId, deviceUpdateMsg, edge); - return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null); + return Futures.immediateFuture(null); case ENTITY_DELETED_RPC_MESSAGE: Device deviceToDelete = deviceService.findDeviceById(tenantId, deviceId); if (deviceToDelete != null) { @@ -232,6 +231,12 @@ public abstract class DeviceEdgeProcessor extends BaseDeviceProcessor implements DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) .addDeviceUpdateMsg(deviceUpdateMsg); + DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(edgeEvent.getTenantId(), deviceId); + if (deviceCredentials != null) { + DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = ((DeviceMsgConstructor) + deviceMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructDeviceCredentialsUpdatedMsg(deviceCredentials); + builder.addDeviceCredentialsUpdateMsg(deviceCredentialsUpdateMsg).build(); + } if (UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE.equals(msgType)) { DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileById(edgeEvent.getTenantId(), device.getDeviceProfileId()); deviceProfile = checkIfDeviceProfileDefaultFieldsAssignedToEdge(edgeEvent.getTenantId(), edgeId, deviceProfile, edgeVersion); @@ -269,22 +274,7 @@ public abstract class DeviceEdgeProcessor extends BaseDeviceProcessor implements deviceMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)) .constructDeviceRpcCallMsg(edgeEvent.getEntityId(), edgeEvent.getBody())) .build(); - case CREDENTIALS_REQUEST: - return convertCredentialsRequestEventToDownlink(edgeEvent); } return downlinkMsg; } - - private DownlinkMsg convertCredentialsRequestEventToDownlink(EdgeEvent edgeEvent) { - DeviceId deviceId = new DeviceId(edgeEvent.getEntityId()); - DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = DeviceCredentialsRequestMsg.newBuilder() - .setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) - .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) - .build(); - DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() - .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) - .addDeviceCredentialsRequestMsg(deviceCredentialsRequestMsg); - return builder.build(); - } - } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java index 30f74ae42d..f63aa8b829 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java @@ -61,10 +61,19 @@ public class RuleChainEdgeProcessor extends BaseEdgeProcessor { RuleChainUpdateMsg ruleChainUpdateMsg = ((RuleChainMsgConstructor) ruleChainMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)) .constructRuleChainUpdatedMsg(msgType, ruleChain, isRoot); - downlinkMsg = DownlinkMsg.newBuilder() + + DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) - .addRuleChainUpdateMsg(ruleChainUpdateMsg) - .build(); + .addRuleChainUpdateMsg(ruleChainUpdateMsg); + + RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId); + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = ((RuleChainMsgConstructor) + ruleChainMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)) + .constructRuleChainMetadataUpdatedMsg(edgeEvent.getTenantId(), msgType, ruleChainMetaData, edgeVersion); + if (ruleChainMetadataUpdateMsg != null) { + builder.addRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg); + } + downlinkMsg = builder.build(); } } case DELETED, UNASSIGNED_FROM_EDGE -> downlinkMsg = DownlinkMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/user/UserEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/user/UserEdgeProcessor.java index 607c5e665c..cd072b4a1e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/user/UserEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/user/UserEdgeProcessor.java @@ -43,10 +43,16 @@ public class UserEdgeProcessor extends BaseEdgeProcessor { User user = userService.findUserById(edgeEvent.getTenantId(), userId); if (user != null) { UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction()); - downlinkMsg = DownlinkMsg.newBuilder() + DownlinkMsg.Builder builder = DownlinkMsg.newBuilder() .setDownlinkMsgId(EdgeUtils.nextPositiveInt()) - .addUserUpdateMsg(((UserMsgConstructor) userMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructUserUpdatedMsg(msgType, user)) - .build(); + .addUserUpdateMsg(((UserMsgConstructor) userMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructUserUpdatedMsg(msgType, user)); + UserCredentials userCredentialsByUserId = userService.findUserCredentialsByUserId(edgeEvent.getTenantId(), userId); + if (userCredentialsByUserId != null && userCredentialsByUserId.isEnabled()) { + UserCredentialsUpdateMsg userCredentialsUpdateMsg = + ((UserMsgConstructor) userMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructUserCredentialsUpdatedMsg(userCredentialsByUserId); + builder.addUserCredentialsUpdateMsg(userCredentialsUpdateMsg); + } + downlinkMsg = builder.build(); } } case DELETED -> downlinkMsg = DownlinkMsg.newBuilder() diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java index 3f61734801..6e4117869b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/sync/DefaultEdgeRequestsService.java @@ -82,8 +82,6 @@ import java.util.UUID; @Slf4j public class DefaultEdgeRequestsService implements EdgeRequestsService { - private static final int DEFAULT_PAGE_SIZE = 1000; - @Autowired private EdgeEventService edgeEventService; @@ -142,8 +140,10 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { private ListenableFuture processEntityAttributesAndAddToEdgeQueue(TenantId tenantId, EntityId entityId, Edge edge, EdgeEventType entityType, String scope, List ssAttributes, AttributesRequestMsg attributesRequestMsg) { + Map entityData = null; + ObjectNode attributes = null; + ListenableFuture future; try { - ListenableFuture future; if (ssAttributes == null || ssAttributes.isEmpty()) { log.trace("[{}][{}] No attributes found for entity {} [{}]", tenantId, edge.getName(), @@ -151,8 +151,8 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { entityId.getId()); future = Futures.immediateFuture(null); } else { - Map entityData = new HashMap<>(); - ObjectNode attributes = JacksonUtil.newObjectNode(); + entityData = new HashMap<>(); + attributes = JacksonUtil.newObjectNode(); for (AttributeKvEntry attr : ssAttributes) { if (DefaultDeviceStateService.PERSISTENT_ATTRIBUTES.contains(attr.getKey()) && !DefaultDeviceStateService.INACTIVITY_TIMEOUT.equals(attr.getKey())) { @@ -170,7 +170,7 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { attributes.put(attr.getKey(), attr.getValueAsString()); } } - if (attributes.size() > 0) { + if (!attributes.isEmpty()) { entityData.put("kv", attributes); entityData.put("scope", scope); JsonNode body = JacksonUtil.valueToTree(entityData); @@ -182,12 +182,13 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService { } return Futures.transformAsync(future, v -> processLatestTimeseriesAndAddToEdgeQueue(tenantId, entityId, edge, entityType), dbCallbackExecutorService); } catch (Exception e) { - String errMsg = String.format("[%s][%s] Failed to save attribute updates to the edge [%s]", tenantId, edge.getId(), attributesRequestMsg); + String errMsg = String.format("[%s][%s] Failed to save attribute updates to the edge [%s], scope = %s, entityData = %s, attributes = %s", + tenantId, edge.getId(), attributesRequestMsg, scope, entityData, attributes); log.error(errMsg, e); return Futures.immediateFailedFuture(new RuntimeException(errMsg, e)); } } - + private ListenableFuture processLatestTimeseriesAndAddToEdgeQueue(TenantId tenantId, EntityId entityId, Edge edge, EdgeEventType entityType) { ListenableFuture> getAllLatestFuture = timeseriesService.findAllLatest(tenantId, entityId); diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java index b05ece9c61..d527492d98 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java @@ -183,7 +183,7 @@ public class DefaultTbDeviceService extends AbstractTbEntityService implements T try { DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(tenantId, deviceCredentials)); logEntityActionService.logEntityAction(tenantId, deviceId, device, device.getCustomerId(), - actionType, user, deviceCredentials); + actionType, user, result); return result; } catch (Exception e) { logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.DEVICE), diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/ImagesUpdater.java b/application/src/main/java/org/thingsboard/server/service/install/update/ImagesUpdater.java index 501cd788e3..3914f049ce 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/ImagesUpdater.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/ImagesUpdater.java @@ -147,7 +147,7 @@ public class ImagesUpdater { try { entity = dao.findById(TenantId.SYS_TENANT_ID, id.getId()); } catch (Exception e) { - log.error("Failed to update {} images: error fetching {} by id [{}]: {}", type, type, id.getId(), StringUtils.abbreviate(e.toString(), 1000)); + log.error("Failed to update {} images: error fetching entity by id [{}]: {}", type, id.getId(), StringUtils.abbreviate(e.toString(), 1000)); continue; } try { 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 b20abb001e..632ea44940 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 @@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.query.EntityDataQuery; import org.thingsboard.server.common.data.query.EntityKey; import org.thingsboard.server.common.data.query.EntityKeyType; import org.thingsboard.server.common.data.query.TsValue; +import org.thingsboard.server.common.msg.tools.TbRateLimitsException; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.entity.EntityService; @@ -355,6 +356,9 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc private void handleWsCmdRuntimeException(String sessionId, RuntimeException e, EntityDataCmd cmd) { log.debug("[{}] Failed to process ws cmd: {}", sessionId, cmd, e); + if (e instanceof TbRateLimitsException) { + return; + } wsService.close(sessionId, CloseStatus.SERVICE_RESTARTED); } 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 9367439d4f..8fdb18cd1d 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 @@ -18,12 +18,15 @@ package org.thingsboard.server.service.subscription; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; +import org.thingsboard.common.util.DeduplicationUtil; import org.thingsboard.common.util.DonAsynchron; import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.common.util.ThingsBoardThreadFactory; +import org.thingsboard.server.cache.limits.RateLimitService; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.EntityType; @@ -36,10 +39,12 @@ import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; import org.thingsboard.server.common.data.kv.ReadTsKvQuery; import org.thingsboard.server.common.data.kv.TsKvEntry; +import org.thingsboard.server.common.data.limit.LimitedApi; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; +import org.thingsboard.server.common.msg.tools.TbRateLimitsException; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.gen.transport.TransportProtos; @@ -48,6 +53,7 @@ import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.discovery.event.ClusterTopologyChangeEvent; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.ws.WebSocketService; +import org.thingsboard.server.service.ws.WebSocketSessionRef; import org.thingsboard.server.service.ws.notification.sub.NotificationRequestUpdate; import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscriptionUpdate; import org.thingsboard.server.service.ws.telemetry.sub.AlarmSubscriptionUpdate; @@ -88,13 +94,20 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer private final TbClusterService clusterService; private final SubscriptionManagerService subscriptionManagerService; private final WebSocketService webSocketService; + private final RateLimitService rateLimitService; private ExecutorService tsCallBackExecutor; private ScheduledExecutorService staleSessionCleanupExecutor; + @Value("${server.ws.rate_limits.subscriptions_per_tenant:2000:60}") + private String subscriptionsPerTenantRateLimit; + @Value("${server.ws.rate_limits.subscriptions_per_user:500:60}") + private String subscriptionsPerUserRateLimit; + public DefaultTbLocalSubscriptionService(AttributesService attrService, TimeseriesService tsService, TbServiceInfoProvider serviceInfoProvider, PartitionService partitionService, TbClusterService clusterService, - @Lazy SubscriptionManagerService subscriptionManagerService, @Lazy WebSocketService webSocketService) { + @Lazy SubscriptionManagerService subscriptionManagerService, @Lazy WebSocketService webSocketService, + RateLimitService rateLimitService) { this.attrService = attrService; this.tsService = tsService; this.serviceInfoProvider = serviceInfoProvider; @@ -102,6 +115,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer this.clusterService = clusterService; this.subscriptionManagerService = subscriptionManagerService; this.webSocketService = webSocketService; + this.rateLimitService = rateLimitService; } private String serviceId; @@ -185,9 +199,18 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer } @Override - public void addSubscription(TbSubscription subscription) { + public void addSubscription(TbSubscription subscription, WebSocketSessionRef sessionRef) { TenantId tenantId = subscription.getTenantId(); EntityId entityId = subscription.getEntityId(); + if (!rateLimitService.checkRateLimit(LimitedApi.WS_SUBSCRIPTIONS, (Object) tenantId, subscriptionsPerTenantRateLimit)) { + handleRateLimitError(subscription, sessionRef, "Exceeded rate limit for WS subscriptions per tenant"); + return; + } + if (sessionRef.getSecurityCtx() != null && !rateLimitService.checkRateLimit(LimitedApi.WS_SUBSCRIPTIONS, sessionRef.getSecurityCtx().getId(), subscriptionsPerUserRateLimit)) { + handleRateLimitError(subscription, sessionRef, "Exceeded rate limit for WS subscriptions per user"); + return; + } + log.debug("[{}][{}] Register subscription: {}", tenantId, entityId, subscription); SubscriptionModificationResult result; subsLock.lock(); @@ -584,4 +607,13 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer subscriptionsBySessionId.keySet().forEach(webSocketService::cleanupIfStale); } + private void handleRateLimitError(TbSubscription subscription, WebSocketSessionRef sessionRef, String message) { + String deduplicationKey = sessionRef.getSessionId() + message; + if (!DeduplicationUtil.alreadyProcessed(deduplicationKey, TimeUnit.SECONDS.toMillis(15))) { + log.info("{} {}", sessionRef, message); + webSocketService.sendError(sessionRef, subscription.getSubscriptionId(), SubscriptionErrorCode.BAD_REQUEST, message); + } + throw new TbRateLimitsException(message); + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/TbAbstractDataSubCtx.java b/application/src/main/java/org/thingsboard/server/service/subscription/TbAbstractDataSubCtx.java index f65eec8453..77ef960d72 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/TbAbstractDataSubCtx.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/TbAbstractDataSubCtx.java @@ -132,7 +132,7 @@ public abstract class TbAbstractDataSubCtx> keysByType = getEntityKeyByTypeMap(keys); for (EntityData entityData : data.getData()) { List entitySubscriptions = addSubscriptions(entityData, keysByType, latestValues, startTs, endTs); - entitySubscriptions.forEach(localSubscriptionService::addSubscription); + entitySubscriptions.forEach(subscription -> localSubscriptionService.addSubscription(subscription, sessionRef)); } } @@ -254,4 +254,5 @@ public abstract class TbAbstractDataSubCtx { .scope(TbAttributeSubscriptionScope.SERVER_SCOPE) .build(); subToDynamicValueKeySet.add(subIdx); - localSubscriptionService.addSubscription(sub); + localSubscriptionService.addSubscription(sub, sessionRef); } } catch (InterruptedException | ExecutionException e) { log.info("[{}][{}][{}] Failed to resolve dynamic values: {}", tenantId, customerId, userId, dynamicValues.keySet()); diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/TbAlarmDataSubCtx.java b/application/src/main/java/org/thingsboard/server/service/subscription/TbAlarmDataSubCtx.java index 0d1f2f94b2..828da388fb 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/TbAlarmDataSubCtx.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/TbAlarmDataSubCtx.java @@ -177,7 +177,7 @@ public class TbAlarmDataSubCtx extends TbAbstractDataSubCtx { .updateProcessor((sub, update) -> sendWsMsg(sub.getSessionId(), update)) .ts(startTs) .build(); - localSubscriptionService.addSubscription(subscription); + localSubscriptionService.addSubscription(subscription, sessionRef); } @Override @@ -342,7 +342,7 @@ public class TbAlarmDataSubCtx extends TbAbstractDataSubCtx { newSubsList.forEach(entity -> createAlarmSubscriptionForEntity(query.getPageLink(), startTs, entity)); } subIdsToCancel.forEach(subId -> localSubscriptionService.cancelSubscription(getSessionId(), subId)); - subsToAdd.forEach(localSubscriptionService::addSubscription); + subsToAdd.forEach(subscription -> localSubscriptionService.addSubscription(subscription, sessionRef)); } private void resetInvocationCounter() { @@ -361,4 +361,5 @@ public class TbAlarmDataSubCtx extends TbAbstractDataSubCtx { EntityDataPageLink edpl = new EntityDataPageLink(maxEntitiesPerAlarmSubscription, 0, null, entitiesSortOrder); return new EntityDataQuery(query.getEntityFilter(), edpl, query.getEntityFields(), query.getLatestValues(), query.getKeyFilters()); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/TbEntityDataSubCtx.java b/application/src/main/java/org/thingsboard/server/service/subscription/TbEntityDataSubCtx.java index 98ec81b798..48458ca6fd 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/TbEntityDataSubCtx.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/TbEntityDataSubCtx.java @@ -226,7 +226,7 @@ public class TbEntityDataSubCtx extends TbAbstractDataSubCtx { } } subIdsToCancel.forEach(subId -> localSubscriptionService.cancelSubscription(getSessionId(), subId)); - subsToAdd.forEach(localSubscriptionService::addSubscription); + subsToAdd.forEach(subscription -> localSubscriptionService.addSubscription(subscription, sessionRef)); sendWsMsg(new EntityDataUpdate(cmdId, data, null, maxEntitiesPerDataSubscription)); } @@ -239,4 +239,5 @@ public class TbEntityDataSubCtx extends TbAbstractDataSubCtx { protected EntityDataQuery buildEntityDataQuery() { return query; } + } diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/TbLocalSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/TbLocalSubscriptionService.java index ddb2a1b590..59e7ad532d 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/TbLocalSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/TbLocalSubscriptionService.java @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.discovery.event.ClusterTopologyChangeEvent; +import org.thingsboard.server.service.ws.WebSocketSessionRef; import org.thingsboard.server.service.ws.notification.sub.NotificationRequestUpdate; import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscriptionUpdate; @@ -29,7 +30,7 @@ import java.util.List; public interface TbLocalSubscriptionService { - void addSubscription(TbSubscription subscription); + void addSubscription(TbSubscription subscription, WebSocketSessionRef sessionRef); void onSubEventCallback(TransportProtos.TbEntitySubEventCallbackProto subEventCallback, TbCallback callback); diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DefaultEntityExportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DefaultEntityExportService.java index 77996a8b7f..26c0771c20 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DefaultEntityExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DefaultEntityExportService.java @@ -22,6 +22,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.ExportableEntity; +import org.thingsboard.server.common.data.HasVersion; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; @@ -74,6 +75,9 @@ public class DefaultEntityExportService cmdHandler.handle(sessionRef, cmd)); + } catch (TbRateLimitsException e) { + log.debug("{} Failed to handle WS cmd: {}", sessionRef, cmd, e); } catch (Exception e) { - log.error("[sessionId: {}, tenantId: {}, userId: {}] Failed to handle WS cmd: {}", sessionId, - sessionRef.getSecurityCtx().getTenantId(), sessionRef.getSecurityCtx().getId(), cmd, e); + log.error("{} Failed to handle WS cmd: {}", sessionRef, cmd, e); } } } @@ -467,7 +469,7 @@ public class DefaultWebSocketService implements WebSocketService { subLock.lock(); try { - oldSubService.addSubscription(sub); + oldSubService.addSubscription(sub, sessionRef); sendUpdate(sessionRef, new TelemetrySubscriptionUpdate(cmd.getCmdId(), attributesData)); } finally { subLock.unlock(); @@ -580,7 +582,7 @@ public class DefaultWebSocketService implements WebSocketService { subLock.lock(); try { - oldSubService.addSubscription(sub); + oldSubService.addSubscription(sub, sessionRef); sendUpdate(sessionRef, new TelemetrySubscriptionUpdate(cmd.getCmdId(), attributesData)); } finally { subLock.unlock(); @@ -677,7 +679,7 @@ public class DefaultWebSocketService implements WebSocketService { subLock.lock(); try { - oldSubService.addSubscription(sub); + oldSubService.addSubscription(sub, sessionRef); sendUpdate(sessionRef, new TelemetrySubscriptionUpdate(cmd.getCmdId(), data)); } finally { subLock.unlock(); @@ -732,7 +734,7 @@ public class DefaultWebSocketService implements WebSocketService { subLock.lock(); try { - oldSubService.addSubscription(sub); + oldSubService.addSubscription(sub, sessionRef); sendUpdate(sessionRef, new TelemetrySubscriptionUpdate(cmd.getCmdId(), data)); } finally { subLock.unlock(); diff --git a/application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java b/application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java index b8c83fe286..285c58a0f5 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/notification/DefaultNotificationCommandsHandler.java @@ -81,7 +81,7 @@ public class DefaultNotificationCommandsHandler implements NotificationCommandsH .limit(cmd.getLimit()) .notificationTypes(cmd.getTypes()) .build(); - localSubscriptionService.addSubscription(subscription); + localSubscriptionService.addSubscription(subscription, sessionRef); fetchUnreadNotifications(subscription); sendUpdate(sessionRef.getSessionId(), subscription.createFullUpdate()); @@ -99,7 +99,7 @@ public class DefaultNotificationCommandsHandler implements NotificationCommandsH .entityId(securityCtx.getId()) .updateProcessor(this::handleNotificationsCountSubscriptionUpdate) .build(); - localSubscriptionService.addSubscription(subscription); + localSubscriptionService.addSubscription(subscription, sessionRef); fetchUnreadNotificationsCount(subscription); sendUpdate(sessionRef.getSessionId(), subscription.createUpdate()); diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 3c9afc4b33..0dbac50e4b 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -78,6 +78,11 @@ server: max_queue_messages_per_session: "${TB_SERVER_WS_DEFAULT_QUEUE_MESSAGES_PER_SESSION:1000}" # Maximum time between WS session opening and sending auth command auth_timeout_ms: "${TB_SERVER_WS_AUTH_TIMEOUT_MS:10000}" + rate_limits: + # Per-tenant rate limit for WS subscriptions + subscriptions_per_tenant: "${TB_SERVER_WS_SUBSCRIPTIONS_PER_TENANT_RATE_LIMIT:2000:60}" + # Per-user rate limit for WS subscriptions + subscriptions_per_user: "${TB_SERVER_WS_SUBSCRIPTIONS_PER_USER_RATE_LIMIT:500:60}" rest: server_side_rpc: # Minimum value of the server-side RPC timeout. May override value provided in the REST API call. @@ -485,7 +490,7 @@ actors: # Cache settings parameters cache: - # caffeine or redis + # caffeine or redis(7.2 - latest compatible version) type: "${CACHE_TYPE:caffeine}" maximumPoolSize: "${CACHE_MAXIMUM_POOL_SIZE:16}" # max pool size to process futures that call the external cache attributes: @@ -768,7 +773,28 @@ spring: leakDetectionThreshold: "${SPRING_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}" # This property increases the number of connections in the pool as demand increases. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability maximumPoolSize: "${SPRING_DATASOURCE_MAXIMUM_POOL_SIZE:16}" - registerMbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # true - enable MBean to diagnose pools state via JMX + # Enable MBean to diagnose pools state via JMX + registerMbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" + events: + # Enable dedicated datasource (a separate database) for events and audit logs. + # Before enabling this, make sure you have set up the following tables in the new DB: + # error_event, lc_event, rule_chain_debug_event, rule_node_debug_event, stats_event, audit_log + enabled: "${SPRING_DEDICATED_EVENTS_DATASOURCE_ENABLED:false}" + # Database driver for Spring JPA for events datasource + driverClassName: "${SPRING_EVENTS_DATASOURCE_DRIVER_CLASS_NAME:org.postgresql.Driver}" + # Database connection URL for events datasource + url: "${SPRING_EVENTS_DATASOURCE_URL:jdbc:postgresql://localhost:5432/thingsboard_events}" + # Database username for events datasource + username: "${SPRING_EVENTS_DATASOURCE_USERNAME:postgres}" + # Database user password for events datasource + password: "${SPRING_EVENTS_DATASOURCE_PASSWORD:postgres}" + hikari: + # This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak for events datasource. A value of 0 means leak detection is disabled + leakDetectionThreshold: "${SPRING_EVENTS_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}" + # This property increases the number of connections in the pool as demand increases for events datasource. At the same time, the property ensures that the pool doesn't grow to the point of exhausting a system's resources, which ultimately affects an application's performance and availability + maximumPoolSize: "${SPRING_EVENTS_DATASOURCE_MAXIMUM_POOL_SIZE:16}" + # Enable MBean to diagnose pools state via JMX for events datasource + registerMbeans: "${SPRING_EVENTS_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # Audit log parameters audit-log: 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 b7cc42c7ac..d0824bcd6d 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -526,7 +526,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { JsonNode activateRequest = getActivateRequest(password); ResultActions resultActions = doPost("/api/noauth/activate", activateRequest); resultActions.andExpect(status().isOk()); - return savedUser; + return doGet("/api/user/" + savedUser.getId(), User.class); } private JsonNode getActivateRequest(String password) throws Exception { diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java index 5005e6ad34..2386b91c6e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.core.type.TypeReference; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; @@ -64,6 +65,7 @@ public class AuditLogControllerTest extends AbstractControllerTest { @Autowired private AuditLogDao auditLogDao; + @Getter @SpyBean private SqlPartitioningRepository partitioningRepository; @SpyBean @@ -161,7 +163,7 @@ public class AuditLogControllerTest extends AbstractControllerTest { Device savedDevice = doPost("/api/device", device, Device.class); for (int i = 0; i < 11; i++) { savedDevice.setName("Device name" + i); - doPost("/api/device", savedDevice, Device.class); + savedDevice = doPost("/api/device", savedDevice, Device.class); } List loadedAuditLogs = new ArrayList<>(); @@ -183,12 +185,12 @@ public class AuditLogControllerTest extends AbstractControllerTest { @Test public void whenSavingNewAuditLog_thenCheckAndCreatePartitionIfNotExists() throws ParseException { long entityTs = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2024-01-01T01:43:11Z").getTime(); - reset(partitioningRepository); + reset(getPartitioningRepository()); AuditLog auditLog = createAuditLog(ActionType.LOGIN, tenantAdminUserId, entityTs); - verify(partitioningRepository).createPartitionIfNotExists(eq("audit_log"), eq(auditLog.getCreatedTime()), eq(partitionDurationInMs)); + verify(getPartitioningRepository()).createPartitionIfNotExists(eq("audit_log"), eq(auditLog.getCreatedTime()), eq(partitionDurationInMs)); - List partitions = partitioningRepository.fetchPartitions("audit_log"); - assertThat(partitions).contains(partitioningRepository.calculatePartitionStartTime(auditLog.getCreatedTime(), partitionDurationInMs)); + List partitions = getPartitioningRepository().fetchPartitions("audit_log"); + assertThat(partitions).contains(getPartitioningRepository().calculatePartitionStartTime(auditLog.getCreatedTime(), partitionDurationInMs)); } @Test @@ -197,15 +199,15 @@ public class AuditLogControllerTest extends AbstractControllerTest { final long oldAuditLogTs = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-10-01T00:00:00Z").getTime(); final long currentTimeMillis = oldAuditLogTs + TimeUnit.SECONDS.toMillis(auditLogsTtlInSec) * 2; - final long partitionStartTs = partitioningRepository.calculatePartitionStartTime(oldAuditLogTs, partitionDurationInMs); - partitioningRepository.createPartitionIfNotExists("audit_log", oldAuditLogTs, partitionDurationInMs); - List partitions = partitioningRepository.fetchPartitions("audit_log"); + final long partitionStartTs = getPartitioningRepository().calculatePartitionStartTime(oldAuditLogTs, partitionDurationInMs); + getPartitioningRepository().createPartitionIfNotExists("audit_log", oldAuditLogTs, partitionDurationInMs); + List partitions = getPartitioningRepository().fetchPartitions("audit_log"); assertThat(partitions).contains(partitionStartTs); willReturn(currentTimeMillis).given(auditLogsCleanUpService).getCurrentTimeMillis(); auditLogsCleanUpService.cleanUp(); - partitions = partitioningRepository.fetchPartitions("audit_log"); + partitions = getPartitioningRepository().fetchPartitions("audit_log"); assertThat(partitions).as("partitions cleared").doesNotContain(partitionStartTs); assertThat(partitions).as("only newer partitions left").allSatisfy(partitionsStart -> { long partitionEndTs = partitionsStart + partitionDurationInMs; @@ -218,18 +220,18 @@ public class AuditLogControllerTest extends AbstractControllerTest { // creating partition bigger than sql.audit_logs.partition_size long entityTs = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-29T07:43:11Z").getTime(); //the partition 7 days is overlapping default partition size 1 day, use in the far past to not affect other tests - partitioningRepository.createPartitionIfNotExists("audit_log", entityTs, TimeUnit.DAYS.toMillis(7)); - List partitions = partitioningRepository.fetchPartitions("audit_log"); + getPartitioningRepository().createPartitionIfNotExists("audit_log", entityTs, TimeUnit.DAYS.toMillis(7)); + List partitions = getPartitioningRepository().fetchPartitions("audit_log"); log.warn("entityTs [{}], fetched partitions {}", entityTs, partitions); assertThat(partitions).contains(ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-28T00:00:00Z").getTime()); - partitioningRepository.cleanupPartitionsCache("audit_log", entityTs, 0); + getPartitioningRepository().cleanupPartitionsCache("audit_log", entityTs, 0); assertDoesNotThrow(() -> { // expecting partition overlap error on partition save createAuditLog(ActionType.LOGIN, tenantAdminUserId, entityTs); }); - assertThat(partitioningRepository.fetchPartitions("audit_log")) - .contains(ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-28T00:00:00Z").getTime());; + assertThat(getPartitioningRepository().fetchPartitions("audit_log")) + .contains(ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-04-28T00:00:00Z").getTime()); } private AuditLog createAuditLog(ActionType actionType, EntityId entityId, long entityTs) { diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java new file mode 100644 index 0000000000..7678b2a91f --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java @@ -0,0 +1,36 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.Getter; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedEventsSqlPartitioningRepository; + +@DaoSqlTest +@TestPropertySource(properties = { + "spring.datasource.events.enabled=true", + "spring.datasource.events.url=${spring.datasource.url}", + "spring.datasource.events.driverClassName=${spring.datasource.driverClassName}", +}) +public class AuditLogControllerTest_DedicatedEventsDataSource extends AuditLogControllerTest { + + @Getter + @SpyBean + private DedicatedEventsSqlPartitioningRepository partitioningRepository; + +} diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java index 512dd434dc..cf46d0f7fd 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java @@ -192,7 +192,7 @@ public class DeviceControllerTest extends AbstractControllerTest { Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService); savedDevice.setName("My new device"); - doPost("/api/device", savedDevice, Device.class); + savedDevice = doPost("/api/device", savedDevice, Device.class); testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED); @@ -247,7 +247,7 @@ public class DeviceControllerTest extends AbstractControllerTest { Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService); savedDevice.setName("My new device"); - doPost("/api/device", savedDevice, Device.class); + savedDevice = doPost("/api/device", savedDevice, Device.class); testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED); @@ -749,8 +749,7 @@ public class DeviceControllerTest extends AbstractControllerTest { Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService); - doPost("/api/device/credentials", deviceCredentials) - .andExpect(status().isOk()); + deviceCredentials = doPost("/api/device/credentials", deviceCredentials, DeviceCredentials.class); testNotifyEntityMsgToEdgePushMsgToCoreOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.CREDENTIALS_UPDATED, deviceCredentials); @@ -1586,10 +1585,33 @@ public class DeviceControllerTest extends AbstractControllerTest { Assert.assertEquals(newAttributeValue, actualAttribute.get("value")); } + @Test + public void testSaveDeviceWithOutdatedVersion() throws Exception { + Device device = createDevice("Device v1.0"); + assertThat(device.getVersion()).isOne(); + + device.setName("Device v2.0"); + device = doPost("/api/device", device, Device.class); + assertThat(device.getVersion()).isEqualTo(2); + + device.setName("Device v1.1"); + device.setVersion(1L); + String response = doPost("/api/device", device).andExpect(status().isConflict()) + .andReturn().getResponse().getContentAsString(); + assertThat(JacksonUtil.toJsonNode(response).get("message").asText()) + .containsIgnoringCase("already changed by someone else"); + + device.setVersion(null); // overriding entity + device = doPost("/api/device", device, Device.class); + assertThat(device.getName()).isEqualTo("Device v1.1"); + assertThat(device.getVersion()).isEqualTo(3); + } + private Device createDevice(String name) { Device device = new Device(); device.setName(name); device.setType("default"); return doPost("/api/device", device, Device.class); } + } 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 49dfa71223..de530b5268 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java @@ -55,14 +55,18 @@ import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; 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.id.TenantProfileId; 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.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.model.JwtSettings; import org.thingsboard.server.dao.edge.EdgeDao; import org.thingsboard.server.dao.exception.DataValidationException; @@ -73,11 +77,13 @@ import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg; import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg; +import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; 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.RuleChainMetadataUpdateMsg; import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.v1.SyncCompletedMsg; import org.thingsboard.server.gen.edge.v1.TenantProfileUpdateMsg; @@ -93,6 +99,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.UUID; import java.util.concurrent.TimeUnit; import static org.hamcrest.Matchers.containsString; @@ -887,23 +894,24 @@ public class EdgeControllerTest extends AbstractControllerTest { edgeImitator.ignoreType(UserCredentialsUpdateMsg.class); edgeImitator.ignoreType(OAuth2UpdateMsg.class); - edgeImitator.expectMessageAmount(24); + edgeImitator.expectMessageAmount(27); edgeImitator.connect(); waitForMessages(edgeImitator); - verifyFetchersMsgs(edgeImitator); + verifyFetchersMsgs(edgeImitator, savedDevice); // verify queue msgs Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1")); + Assert.assertTrue(popDeviceCredentialsMsg(edgeImitator.getDownlinkMsgs(), savedDevice.getId())); Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "test")); Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1")); Assert.assertTrue(edgeImitator.getDownlinkMsgs().isEmpty()); - edgeImitator.expectMessageAmount(20); + edgeImitator.expectMessageAmount(22); doPost("/api/edge/sync/" + edge.getId()); waitForMessages(edgeImitator); - verifyFetchersMsgs(edgeImitator); + verifyFetchersMsgs(edgeImitator, savedDevice); Assert.assertTrue(edgeImitator.getDownlinkMsgs().isEmpty()); edgeImitator.allowIgnoredTypes(); @@ -920,6 +928,23 @@ public class EdgeControllerTest extends AbstractControllerTest { .andExpect(status().isOk()); } + private RuleChainId getEdgeRootRuleChainId(EdgeImitator edgeImitator) { + try { + EdgeId edgeId = new EdgeId(new UUID(edgeImitator.getConfiguration().getEdgeIdMSB(), edgeImitator.getConfiguration().getEdgeIdLSB())); + List edgeRuleChains = doGetTypedWithPageLink("/api/edge/" + edgeId.getId() + "/ruleChains?", + new TypeReference>() { + }, new PageLink(100)).getData(); + for (RuleChain edgeRuleChain : edgeRuleChains) { + if (edgeRuleChain.isRoot()) { + return edgeRuleChain.getId(); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + throw new RuntimeException("Root rule chain not found"); + } + private void simulateEdgeActivation(Edge edge) throws Exception { ObjectNode attributes = JacksonUtil.newObjectNode(); attributes.put("active", true); @@ -949,9 +974,10 @@ public class EdgeControllerTest extends AbstractControllerTest { } } - private void verifyFetchersMsgs(EdgeImitator edgeImitator) { + private void verifyFetchersMsgs(EdgeImitator edgeImitator, Device savedDevice) { Assert.assertTrue(popQueueMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Main")); Assert.assertTrue(popRuleChainMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Edge Root Rule Chain")); + Assert.assertTrue(popRuleChainMetadataMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, getEdgeRootRuleChainId(edgeImitator))); Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "general")); Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "mail")); Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "connectivity")); @@ -965,6 +991,7 @@ public class EdgeControllerTest extends AbstractControllerTest { Assert.assertTrue(popCustomerMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Public")); Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default")); Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1")); + Assert.assertTrue(popDeviceCredentialsMsg(edgeImitator.getDownlinkMsgs(), savedDevice.getId())); Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "test")); Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1")); Assert.assertTrue(popTenantMsg(edgeImitator.getDownlinkMsgs(), tenantId)); @@ -1002,6 +1029,21 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } + private boolean popRuleChainMetadataMsg(List messages, UpdateMsgType msgType, RuleChainId ruleChainId) { + for (AbstractMessage message : messages) { + if (message instanceof RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg) { + RuleChainMetaData ruleChainMetaData = JacksonUtil.fromString(ruleChainMetadataUpdateMsg.getEntity(), RuleChainMetaData.class, true); + Assert.assertNotNull(ruleChainMetaData); + if (msgType.equals(ruleChainMetadataUpdateMsg.getMsgType()) + && ruleChainId.equals(ruleChainMetaData.getRuleChainId())) { + messages.remove(message); + return true; + } + } + } + return false; + } + private boolean popAdminSettingsMsg(List messages, String key) { for (AbstractMessage message : messages) { if (message instanceof AdminSettingsUpdateMsg adminSettingsUpdateMsg) { @@ -1046,6 +1088,20 @@ public class EdgeControllerTest extends AbstractControllerTest { return false; } + private boolean popDeviceCredentialsMsg(List messages, DeviceId deviceId) { + for (AbstractMessage message : messages) { + if (message instanceof DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) { + DeviceCredentials deviceCredentials = JacksonUtil.fromString(deviceCredentialsUpdateMsg.getEntity(), DeviceCredentials.class, true); + Assert.assertNotNull(deviceCredentials); + if (deviceId.equals(deviceCredentials.getDeviceId())) { + messages.remove(message); + return true; + } + } + } + return false; + } + private boolean popAssetProfileMsg(List messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { if (message instanceof AssetProfileUpdateMsg assetProfileUpdateMsg) { diff --git a/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java index 827ea250ed..9e70a00f2f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java @@ -176,7 +176,7 @@ public class EntityViewControllerTest extends AbstractControllerTest { savedView.setName("New test entity view"); - doPost("/api/entityView", savedView, EntityView.class); + savedView = doPost("/api/entityView", savedView, EntityView.class); foundEntityView = doGet("/api/entityView/" + savedView.getId().getId().toString(), EntityView.class); assertEquals(savedView, foundEntityView); diff --git a/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java index a990f55224..949dd4a781 100644 --- a/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java @@ -120,7 +120,7 @@ public class RuleChainControllerTest extends AbstractControllerTest { ActionType.ADDED); savedRuleChain.setName("New RuleChain"); - doPost("/api/ruleChain", savedRuleChain, RuleChain.class); + savedRuleChain = doPost("/api/ruleChain", savedRuleChain, RuleChain.class); RuleChain foundRuleChain = doGet("/api/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class); Assert.assertEquals(savedRuleChain.getName(), foundRuleChain.getName()); diff --git a/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java index 14e597378c..e1beda28d8 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java @@ -149,7 +149,7 @@ public class TenantControllerTest extends AbstractControllerTest { testBroadcastEntityStateChangeEventTimeManyTimeTenant(savedTenant, ComponentLifecycleEvent.CREATED, 1); savedTenant.setTitle("My new tenant"); - saveTenant(savedTenant); + savedTenant = saveTenant(savedTenant); Tenant foundTenant = doGet("/api/tenant/" + savedTenant.getId().getId().toString(), Tenant.class); Assert.assertEquals(foundTenant.getTitle(), savedTenant.getTitle()); @@ -470,7 +470,7 @@ public class TenantControllerTest extends AbstractControllerTest { tenantProfile = doPost("/api/tenantProfile", tenantProfile, TenantProfile.class); tenant.setTenantProfileId(tenantProfile.getId()); - saveTenant(tenant); + tenant = saveTenant(tenant); login(username, password); @@ -500,7 +500,7 @@ public class TenantControllerTest extends AbstractControllerTest { tenantProfile2 = doPost("/api/tenantProfile", tenantProfile2, TenantProfile.class); tenant.setTenantProfileId(tenantProfile2.getId()); - saveTenant(tenant); + tenant = saveTenant(tenant); login(username, password); @@ -542,7 +542,7 @@ public class TenantControllerTest extends AbstractControllerTest { loginSysAdmin(); tenant.setTenantProfileId(null); - saveTenant(tenant); + tenant = saveTenant(tenant); login(username, password); for (Queue queue : foundTenantQueues) { 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 e7f664477c..f7a066f7e0 100644 --- a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java @@ -83,6 +83,7 @@ import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg; import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg; +import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.v1.EdgeConfiguration; @@ -96,6 +97,7 @@ import org.thingsboard.server.gen.edge.v1.TenantProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.TenantUpdateMsg; import org.thingsboard.server.gen.edge.v1.UpdateMsgType; import org.thingsboard.server.gen.edge.v1.UplinkMsg; +import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.v1.UserUpdateMsg; import java.util.ArrayList; @@ -143,7 +145,7 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); edgeImitator.ignoreType(OAuth2UpdateMsg.class); - edgeImitator.expectMessageAmount(21); + edgeImitator.expectMessageAmount(24); edgeImitator.connect(); requestEdgeRuleChainMetadata(); @@ -250,7 +252,7 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { UUID ruleChainUUID = validateRuleChains(); // 1 from request message - validateMsgsCnt(RuleChainMetadataUpdateMsg.class, 1); + validateMsgsCnt(RuleChainMetadataUpdateMsg.class, 2); validateRuleChainMetadataUpdates(ruleChainUUID); // 4 messages ('general', 'mail', 'connectivity', 'jwt') @@ -275,6 +277,8 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { validateMsgsCnt(DeviceUpdateMsg.class, 1); validateDevices(); + validateMsgsCnt(DeviceCredentialsUpdateMsg.class, 1); + // 1 from asset fetcher validateMsgsCnt(AssetUpdateMsg.class, 1); validateAssets(); @@ -287,6 +291,8 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { validateMsgsCnt(UserUpdateMsg.class, 1); validateUsers(); + validateMsgsCnt(UserCredentialsUpdateMsg.class, 1); + // 1 from tenant fetcher validateMsgsCnt(TenantUpdateMsg.class, 1); validateTenant(); 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 9e09a16fd9..071d6b1391 100644 --- a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java @@ -150,25 +150,25 @@ public class DeviceEdgeTest extends AbstractEdgeTest { + "/edge/" + edge.getUuidId(), Edge.class); Assert.assertTrue(edgeImitator.waitForMessages()); - edgeImitator.expectMessageAmount(1); + edgeImitator.expectMessageAmount(2); doPost("/api/customer/" + savedCustomer.getUuidId() + "/device/" + savedDevice.getUuidId(), Device.class); Assert.assertTrue(edgeImitator.waitForMessages()); - latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); - deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; + deviceUpdateMsgOpt = edgeImitator.findMessageByType(DeviceUpdateMsg.class); + Assert.assertTrue(deviceUpdateMsgOpt.isPresent()); + deviceUpdateMsg = deviceUpdateMsgOpt.get(); deviceFromMsg = JacksonUtil.fromString(deviceUpdateMsg.getEntity(), Device.class, true); Assert.assertNotNull(deviceFromMsg); Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); Assert.assertEquals(savedCustomer.getId(), deviceFromMsg.getCustomerId()); // unassign device #2 from customer - edgeImitator.expectMessageAmount(1); + edgeImitator.expectMessageAmount(2); doDelete("/api/customer/device/" + savedDevice.getUuidId(), Device.class); Assert.assertTrue(edgeImitator.waitForMessages()); - latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); - deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; + deviceUpdateMsgOpt = edgeImitator.findMessageByType(DeviceUpdateMsg.class); + Assert.assertTrue(deviceUpdateMsgOpt.isPresent()); + deviceUpdateMsg = deviceUpdateMsgOpt.get(); deviceFromMsg = JacksonUtil.fromString(deviceUpdateMsg.getEntity(), Device.class, true); Assert.assertNotNull(deviceFromMsg); Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); @@ -204,8 +204,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { Assert.assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); deviceCredentials.setCredentialsId("access_token"); - doPost("/api/device/credentials", deviceCredentials) - .andExpect(status().isOk()); + deviceCredentials = doPost("/api/device/credentials", deviceCredentials, DeviceCredentials.class); Assert.assertTrue(edgeImitator.waitForMessages()); AbstractMessage latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof DeviceCredentialsUpdateMsg); @@ -218,8 +217,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { deviceCredentials.setCredentialsType(DeviceCredentialsType.X509_CERTIFICATE); deviceCredentials.setCredentialsId(null); deviceCredentials.setCredentialsValue("-----BEGIN RSA PRIVATE KEY-----"); - doPost("/api/device/credentials", deviceCredentials) - .andExpect(status().isOk()); + deviceCredentials = doPost("/api/device/credentials", deviceCredentials, DeviceCredentials.class); Assert.assertTrue(edgeImitator.waitForMessages()); latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof DeviceCredentialsUpdateMsg); @@ -243,7 +241,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { Assert.assertTrue(edgeImitator.waitForMessages()); // update device - edgeImitator.expectMessageAmount(1); + edgeImitator.expectMessageAmount(2); savedDevice.setFirmwareId(firmwareOtaPackageInfo.getId()); savedDevice.setSoftwareId(softwareOtaPackageInfo.getId()); @@ -256,9 +254,9 @@ public class DeviceEdgeTest extends AbstractEdgeTest { savedDevice = doPost("/api/device", savedDevice, Device.class); Assert.assertTrue(edgeImitator.waitForMessages()); - AbstractMessage latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg); - DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) latestMessage; + Optional deviceUpdateMsgOpt = edgeImitator.findMessageByType(DeviceUpdateMsg.class); + Assert.assertTrue(deviceUpdateMsgOpt.isPresent()); + DeviceUpdateMsg deviceUpdateMsg = deviceUpdateMsgOpt.get(); Device deviceMsg = JacksonUtil.fromString(deviceUpdateMsg.getEntity(), Device.class, true); Assert.assertNotNull(deviceMsg); Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType()); @@ -504,7 +502,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build()); edgeImitator.expectResponsesAmount(1); - edgeImitator.expectMessageAmount(2); + edgeImitator.expectMessageAmount(1); testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder); edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); @@ -526,18 +524,6 @@ public class DeviceEdgeTest extends AbstractEdgeTest { Device device = doGet("/api/device/" + newDeviceId, Device.class); Assert.assertNotNull(device); Assert.assertNotEquals(deviceOnCloudName, device.getName()); - - Optional deviceCredentialsUpdateMsgOpt = edgeImitator.findMessageByType(DeviceCredentialsRequestMsg.class); - Assert.assertTrue(deviceCredentialsUpdateMsgOpt.isPresent()); - DeviceCredentialsRequestMsg latestDeviceCredentialsRequestMsg = deviceCredentialsUpdateMsgOpt.get(); - Assert.assertEquals(deviceMsg.getUuidId().getMostSignificantBits(), latestDeviceCredentialsRequestMsg.getDeviceIdMSB()); - Assert.assertEquals(device.getUuidId().getLeastSignificantBits(), latestDeviceCredentialsRequestMsg.getDeviceIdLSB()); - - newDeviceId = new UUID(latestDeviceCredentialsRequestMsg.getDeviceIdMSB(), latestDeviceCredentialsRequestMsg.getDeviceIdLSB()); - - device = doGet("/api/device/" + newDeviceId, Device.class); - Assert.assertNotNull(device); - Assert.assertNotEquals(deviceOnCloudName, device.getName()); } @Test @@ -553,22 +539,10 @@ public class DeviceEdgeTest extends AbstractEdgeTest { uplinkMsgBuilder.addDeviceUpdateMsg(deviceUpdateMsgBuilder.build()); edgeImitator.expectResponsesAmount(1); - edgeImitator.expectMessageAmount(1); - edgeImitator.sendUplinkMsg(uplinkMsgBuilder.build()); - Assert.assertTrue(edgeImitator.waitForResponses()); - Assert.assertTrue(edgeImitator.waitForMessages()); - AbstractMessage latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof DeviceCredentialsRequestMsg); - DeviceCredentialsRequestMsg latestDeviceCredentialsRequestMsg = (DeviceCredentialsRequestMsg) latestMessage; - Assert.assertEquals(deviceMsg.getUuidId().getMostSignificantBits(), latestDeviceCredentialsRequestMsg.getDeviceIdMSB()); - Assert.assertEquals(deviceMsg.getUuidId().getLeastSignificantBits(), latestDeviceCredentialsRequestMsg.getDeviceIdLSB()); - - UUID newDeviceId = new UUID(latestDeviceCredentialsRequestMsg.getDeviceIdMSB(), latestDeviceCredentialsRequestMsg.getDeviceIdLSB()); - - Device device = doGet("/api/device/" + newDeviceId, Device.class); + Device device = doGet("/api/device/" + deviceMsg.getId().getId(), Device.class); Assert.assertNotNull(device); Assert.assertEquals("Edge Device 2", device.getName()); } diff --git a/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java index 62d2c5eade..c694df84f8 100644 --- a/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java @@ -193,7 +193,7 @@ public class RuleChainEdgeTest extends AbstractEdgeTest { ruleChain.setType(RuleChainType.EDGE); RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class); - edgeImitator.expectMessageAmount(2); + edgeImitator.expectMessageAmount(4); doPost("/api/edge/" + edge.getUuidId() + "/ruleChain/" + savedRuleChain.getUuidId(), RuleChain.class); RuleChainMetaData metaData = createRuleChainMetadata(savedRuleChain); @@ -201,7 +201,7 @@ public class RuleChainEdgeTest extends AbstractEdgeTest { // set new rule chain as root RuleChainId currentRootRuleChainId = edge.getRootRuleChainId(); - edgeImitator.expectMessageAmount(1); + edgeImitator.expectMessageAmount(2); doPost("/api/edge/" + edge.getUuidId() + "/" + savedRuleChain.getUuidId() + "/root", Edge.class); Assert.assertTrue(edgeImitator.waitForMessages()); diff --git a/application/src/test/java/org/thingsboard/server/edge/TelemetryEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/TelemetryEdgeTest.java index 00b8cc4b74..b77e0b5ccc 100644 --- a/application/src/test/java/org/thingsboard/server/edge/TelemetryEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/TelemetryEdgeTest.java @@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg; +import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg; import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.v1.EntityDataProto; import org.thingsboard.server.gen.edge.v1.UplinkMsg; @@ -183,7 +184,7 @@ public class TelemetryEdgeTest extends AbstractEdgeTest { edgeImitator.setRandomFailuresOnTimeseriesDownlink(true); // imitator will generate failure in 100% of timeseries cases edgeImitator.setFailureProbability(100); - edgeImitator.expectMessageAmount(numberOfMsgsToSend); + edgeImitator.expectMessageAmount(numberOfMsgsToSend * 2); for (int idx = 1; idx <= numberOfMsgsToSend; idx++) { String timeseriesData = "{\"data\":{\"idx\":" + idx + "},\"ts\":" + System.currentTimeMillis() + "}"; JsonNode timeseriesEntityData = JacksonUtil.toJsonNode(timeseriesData); @@ -204,6 +205,9 @@ public class TelemetryEdgeTest extends AbstractEdgeTest { List deviceUpdateMsgs = edgeImitator.findAllMessagesByType(DeviceUpdateMsg.class); Assert.assertEquals(numberOfMsgsToSend, deviceUpdateMsgs.size()); + List deviceCredentialsUpdateMsgs = edgeImitator.findAllMessagesByType(DeviceCredentialsUpdateMsg.class); + Assert.assertEquals(numberOfMsgsToSend, deviceCredentialsUpdateMsgs.size()); + edgeImitator.setRandomFailuresOnTimeseriesDownlink(false); } diff --git a/application/src/test/java/org/thingsboard/server/edge/UserEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/UserEdgeTest.java index 6314cf53b9..93fea90c5a 100644 --- a/application/src/test/java/org/thingsboard/server/edge/UserEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/UserEdgeTest.java @@ -47,7 +47,7 @@ public class UserEdgeTest extends AbstractEdgeTest { @Test public void testCreateUpdateDeleteTenantUser() throws Exception { // create user - edgeImitator.expectMessageAmount(3); + edgeImitator.expectMessageAmount(4); User newTenantAdmin = new User(); newTenantAdmin.setAuthority(Authority.TENANT_ADMIN); newTenantAdmin.setTenantId(tenantId); @@ -55,7 +55,7 @@ public class UserEdgeTest extends AbstractEdgeTest { newTenantAdmin.setFirstName("Boris"); newTenantAdmin.setLastName("Johnson"); User savedTenantAdmin = createUser(newTenantAdmin, "tenant"); - Assert.assertTrue(edgeImitator.waitForMessages()); // wait 3 messages - user update msg and x2 user credentials update msgs + Assert.assertTrue(edgeImitator.waitForMessages()); // wait 4 messages - x2 user update msg and x2 user credentials update msgs Optional userUpdateMsgOpt = edgeImitator.findMessageByType(UserUpdateMsg.class); Assert.assertTrue(userUpdateMsgOpt.isPresent()); UserUpdateMsg userUpdateMsg = userUpdateMsgOpt.get(); @@ -71,13 +71,13 @@ public class UserEdgeTest extends AbstractEdgeTest { Assert.assertTrue(userCredentialsUpdateMsgOpt.isPresent()); // update user - edgeImitator.expectMessageAmount(1); + edgeImitator.expectMessageAmount(2); savedTenantAdmin.setLastName("Borisov"); savedTenantAdmin = doPost("/api/user", savedTenantAdmin, User.class); Assert.assertTrue(edgeImitator.waitForMessages()); - AbstractMessage latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof UserUpdateMsg); - userUpdateMsg = (UserUpdateMsg) latestMessage; + userUpdateMsgOpt = edgeImitator.findMessageByType(UserUpdateMsg.class); + Assert.assertTrue(userUpdateMsgOpt.isPresent()); + userUpdateMsg = userUpdateMsgOpt.get(); userMsg = JacksonUtil.fromString(userUpdateMsg.getEntity(), User.class, true); Assert.assertNotNull(userMsg); Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, userUpdateMsg.getMsgType()); @@ -92,7 +92,7 @@ public class UserEdgeTest extends AbstractEdgeTest { changePasswordRequest.setNewPassword("newTenant"); doPost("/api/auth/changePassword", changePasswordRequest); Assert.assertTrue(edgeImitator.waitForMessages()); - latestMessage = edgeImitator.getLatestMessage(); + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof UserCredentialsUpdateMsg); UserCredentialsUpdateMsg userCredentialsUpdateMsg = (UserCredentialsUpdateMsg) latestMessage; UserCredentials userCredentialsMsg = JacksonUtil.fromString(userCredentialsUpdateMsg.getEntity(), UserCredentials.class, true); @@ -131,7 +131,7 @@ public class UserEdgeTest extends AbstractEdgeTest { Assert.assertTrue(edgeImitator.waitForMessages()); // create user - edgeImitator.expectMessageAmount(3); + edgeImitator.expectMessageAmount(4); User customerUser = new User(); customerUser.setAuthority(Authority.CUSTOMER_USER); customerUser.setTenantId(tenantId); @@ -140,7 +140,7 @@ public class UserEdgeTest extends AbstractEdgeTest { customerUser.setFirstName("John"); customerUser.setLastName("Edwards"); User savedCustomerUser = createUser(customerUser, "customer"); - Assert.assertTrue(edgeImitator.waitForMessages()); // wait 3 messages - user update msg and x2 user credentials update msgs + Assert.assertTrue(edgeImitator.waitForMessages()); // wait 4 messages - x2 user update msg and x2 user credentials update msgs Optional userUpdateMsgOpt = edgeImitator.findMessageByType(UserUpdateMsg.class); Assert.assertTrue(userUpdateMsgOpt.isPresent()); UserUpdateMsg userUpdateMsg = userUpdateMsgOpt.get(); @@ -155,13 +155,13 @@ public class UserEdgeTest extends AbstractEdgeTest { Assert.assertEquals(savedCustomerUser.getLastName(), userMsg.getLastName()); // update user - edgeImitator.expectMessageAmount(1); + edgeImitator.expectMessageAmount(2); savedCustomerUser.setLastName("Addams"); savedCustomerUser = doPost("/api/user", savedCustomerUser, User.class); Assert.assertTrue(edgeImitator.waitForMessages()); - AbstractMessage latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof UserUpdateMsg); - userUpdateMsg = (UserUpdateMsg) latestMessage; + userUpdateMsgOpt = edgeImitator.findMessageByType(UserUpdateMsg.class); + Assert.assertTrue(userUpdateMsgOpt.isPresent()); + userUpdateMsg = userUpdateMsgOpt.get(); userMsg = JacksonUtil.fromString(userUpdateMsg.getEntity(), User.class, true); Assert.assertNotNull(userMsg); Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, userUpdateMsg.getMsgType()); @@ -176,7 +176,7 @@ public class UserEdgeTest extends AbstractEdgeTest { changePasswordRequest.setNewPassword("newCustomer"); doPost("/api/auth/changePassword", changePasswordRequest); Assert.assertTrue(edgeImitator.waitForMessages()); - latestMessage = edgeImitator.getLatestMessage(); + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof UserCredentialsUpdateMsg); UserCredentialsUpdateMsg userCredentialsUpdateMsg = (UserCredentialsUpdateMsg) latestMessage; UserCredentials userCredentialsMsg = JacksonUtil.fromString(userCredentialsUpdateMsg.getEntity(), UserCredentials.class, true); diff --git a/application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/AbstractDeviceProcessorTest.java b/application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/AbstractDeviceProcessorTest.java index 0ec40fb908..31524e467a 100644 --- a/application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/AbstractDeviceProcessorTest.java +++ b/application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/AbstractDeviceProcessorTest.java @@ -30,6 +30,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.security.DeviceCredentials; import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.DownlinkMsg; import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessorTest; @@ -61,6 +62,9 @@ public abstract class AbstractDeviceProcessorTest extends BaseEdgeProcessorTest deviceProfile.setProfileData(deviceProfileData); deviceProfile.setTransportType(DeviceTransportType.DEFAULT); + DeviceCredentials deviceCredentials = new DeviceCredentials(); + deviceCredentials.setDeviceId(deviceId); + Device device = new Device(); device.setDeviceProfileId(deviceProfileId); device.setId(deviceId); @@ -71,9 +75,9 @@ public abstract class AbstractDeviceProcessorTest extends BaseEdgeProcessorTest edgeEvent.setTenantId(tenantId); edgeEvent.setAction(EdgeEventActionType.ADDED); - willReturn(device).given(deviceService).findDeviceById(tenantId, deviceId); willReturn(deviceProfile).given(deviceProfileService).findDeviceProfileById(tenantId, deviceProfileId); + willReturn(deviceCredentials).given(deviceCredentialsService).findDeviceCredentialsByDeviceId(tenantId, deviceId); } protected void updateDeviceProfileDefaultFields(long expectedDashboardIdMSB, long expectedDashboardIdLSB, diff --git a/application/src/test/java/org/thingsboard/server/system/RestTemplateConvertersTest.java b/application/src/test/java/org/thingsboard/server/system/RestTemplateConvertersTest.java index 74c2dfda37..5fde907bf1 100644 --- a/application/src/test/java/org/thingsboard/server/system/RestTemplateConvertersTest.java +++ b/application/src/test/java/org/thingsboard/server/system/RestTemplateConvertersTest.java @@ -17,20 +17,45 @@ package org.thingsboard.server.system; import lombok.extern.slf4j.Slf4j; import org.junit.Test; -import org.junit.jupiter.api.Assertions; +import org.springframework.http.MediaType; +import org.springframework.mock.http.client.MockClientHttpRequest; +import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.util.ClassUtils; import org.springframework.web.client.RestTemplate; +import java.nio.charset.StandardCharsets; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + @Slf4j public class RestTemplateConvertersTest { @Test - public void testJacksonXmlConverter() { + public void testMappingJackson2HttpMessageConverterIsUsedInsteadOfMappingJackson2XmlHttpMessageConverter() { ClassLoader classLoader = RestTemplate.class.getClassLoader(); boolean jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader); - Assertions.assertFalse(jackson2XmlPresent, "XmlMapper must not be present in classpath, please, exclude \"jackson-dataformat-xml\" dependency!"); - //If this xml mapper will be present in classpath then we will get "Unsupported Media Type" in RestTemplate + assertThat(jackson2XmlPresent).isTrue(); + + RestTemplate restTemplate = new RestTemplate(); + MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate); + mockServer.expect(requestTo("/test")) + .andExpect(request -> { + MockClientHttpRequest mockRequest = (MockClientHttpRequest) request; + byte[] body = mockRequest.getBodyAsBytes(); + String requestBody = new String(body, StandardCharsets.UTF_8); + assertThat(requestBody).contains("{\"name\":\"test\",\"value\":1}"); + }) + .andRespond(withSuccess("{\"name\":\"test\",\"value\":1}", MediaType.APPLICATION_JSON)); + + TestObject requestObject = new TestObject("test", 1); + TestObject actualObject = restTemplate.postForObject("/test", requestObject, TestObject.class); + assertThat(actualObject).isEqualTo(requestObject); + mockServer.verify(); } + record TestObject(String name, int value) {} + } 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 c7027ed42a..4f24c58916 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, 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()); @@ -145,12 +145,14 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { return tsKvEntries; } - private boolean predicateForStatuses (List ts) { - List statuses = ts.stream().sorted(Comparator - .comparingLong(TsKvEntry::getTs)).map(KvEntry::getValueAsString) + private boolean predicateForStatuses(List ts) { + List statuses = ts.stream() + .sorted(Comparator.comparingLong(TsKvEntry::getTs)) + .map(KvEntry::getValueAsString) .map(OtaPackageUpdateStatus::valueOf) .collect(Collectors.toList()); log.warn("{}", statuses); return statuses.containsAll(expectedStatuses); } + } diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java index 9f74e413ba..f9c22ecc32 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java @@ -39,14 +39,14 @@ public abstract class VersionedCaffeineTbCache versionValuePair = doGet(key); @@ -85,7 +85,7 @@ public abstract class VersionedCaffeineTbCache wrapValue(V value, Long version) { diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java index 7c1e8dc9a6..6ef3918a68 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java @@ -46,20 +46,11 @@ public abstract class VersionedRedisTbCacheI8", currentVersionBytes) if newVersion > currentVersion then setNewValue() end @@ -68,7 +59,7 @@ public abstract class VersionedRedisTbCache valueSerializer) { super(cacheName, cacheSpecsMap, connectionFactory, configuration, valueSerializer); @@ -168,14 +159,4 @@ public abstract class VersionedRedisTbCache { +public class DeviceCaffeineCache extends VersionedCaffeineTbCache { public DeviceCaffeineCache(CacheManager cacheManager) { super(cacheManager, CacheConstants.DEVICE_CACHE); 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 03eea82f09..6e338a175a 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,9 +21,9 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.SerializationException; 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.TbRedisSerializer; +import org.thingsboard.server.cache.VersionedRedisTbCache; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.util.ProtoUtils; @@ -31,7 +31,7 @@ import org.thingsboard.server.gen.transport.TransportProtos; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @Service("DeviceCache") -public class DeviceRedisCache extends RedisTbTransactionalCache { +public class DeviceRedisCache extends VersionedRedisTbCache { public DeviceRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { super(CacheConstants.DEVICE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>() { 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 7972a75340..07b91294f7 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 @@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; @EqualsAndHashCode(callSuper = true) -public class Customer extends ContactBased implements HasTenantId, ExportableEntity, HasTitle { +public class Customer extends ContactBased implements HasTenantId, ExportableEntity, HasTitle, HasVersion { private static final long serialVersionUID = -1599722990298929275L; @@ -42,6 +42,8 @@ public class Customer extends ContactBased implements HasTenantId, E @Getter @Setter private CustomerId externalId; + @Getter @Setter + private Long version; public Customer() { super(); @@ -56,6 +58,7 @@ public class Customer extends ContactBased implements HasTenantId, E this.tenantId = customer.getTenantId(); this.title = customer.getTitle(); this.externalId = customer.getExternalId(); + this.version = customer.getVersion(); } public TenantId getTenantId() { 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 81c7c7683b..a6cc81a51a 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 @@ -18,6 +18,8 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; +import lombok.Getter; +import lombok.Setter; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.TenantId; @@ -29,7 +31,7 @@ import java.util.Objects; import java.util.Set; @Schema -public class DashboardInfo extends BaseData implements HasName, HasTenantId, HasTitle, HasImage { +public class DashboardInfo extends BaseData implements HasName, HasTenantId, HasTitle, HasImage, HasVersion { private static final long serialVersionUID = -9080404114760433799L; @@ -43,6 +45,9 @@ public class DashboardInfo extends BaseData implements HasName, Has private boolean mobileHide; private Integer mobileOrder; + @Getter @Setter + private Long version; + public DashboardInfo() { super(); } @@ -59,6 +64,7 @@ public class DashboardInfo extends BaseData implements HasName, Has this.assignedCustomers = dashboardInfo.getAssignedCustomers(); this.mobileHide = dashboardInfo.isMobileHide(); this.mobileOrder = dashboardInfo.getMobileOrder(); + this.version = dashboardInfo.getVersion(); } @Schema(description = "JSON object with the dashboard Id. " + 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 e7c37d3ed1..f6478f4a0b 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 @@ -22,6 +22,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.device.data.DeviceData; import org.thingsboard.server.common.data.id.CustomerId; @@ -38,8 +39,9 @@ import java.util.Optional; @Schema @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) @Slf4j -public class Device extends BaseDataWithAdditionalInfo implements HasLabel, HasTenantId, HasCustomerId, HasOtaPackage, ExportableEntity { +public class Device extends BaseDataWithAdditionalInfo implements HasLabel, HasTenantId, HasCustomerId, HasOtaPackage, HasVersion, ExportableEntity { private static final long serialVersionUID = 2807343040519543363L; @@ -65,6 +67,8 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL @Getter @Setter private DeviceId externalId; + @Getter @Setter + private Long version; public Device() { super(); @@ -86,6 +90,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.firmwareId = device.getFirmwareId(); this.softwareId = device.getSoftwareId(); this.externalId = device.getExternalId(); + this.version = device.getVersion(); } public Device updateDevice(Device device) { @@ -100,6 +105,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.setSoftwareId(device.getSoftwareId()); Optional.ofNullable(device.getAdditionalInfo()).ifPresent(this::setAdditionalInfo); this.setExternalId(device.getExternalId()); + this.setVersion(device.getVersion()); return this; } @@ -225,33 +231,4 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL return super.getAdditionalInfo(); } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("Device [tenantId="); - builder.append(tenantId); - builder.append(", customerId="); - builder.append(customerId); - builder.append(", name="); - builder.append(name); - builder.append(", type="); - builder.append(type); - builder.append(", label="); - builder.append(label); - builder.append(", deviceProfileId="); - builder.append(deviceProfileId); - builder.append(", deviceData="); - builder.append(firmwareId); - builder.append(", firmwareId="); - builder.append(deviceData); - builder.append(", additionalInfo="); - builder.append(getAdditionalInfo()); - builder.append(", createdTime="); - builder.append(createdTime); - builder.append(", id="); - builder.append(id); - builder.append("]"); - return builder.toString(); - } - } 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 c324f96ac2..6a583afbd1 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 @@ -18,11 +18,13 @@ package org.thingsboard.server.common.data; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.ToString; import org.thingsboard.server.common.data.id.DeviceId; @Schema @Data @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class DeviceInfo extends Device { private static final long serialVersionUID = -3004579925090663691L; 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 6791a460ed..df297ba85e 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 @@ -42,7 +42,7 @@ import java.io.IOException; @ToString(exclude = {"image", "profileDataBytes"}) @EqualsAndHashCode(callSuper = true) @Slf4j -public class DeviceProfile extends BaseData implements HasName, HasTenantId, HasOtaPackage, HasRuleEngineProfile, ExportableEntity, HasImage, HasDefaultOption { +public class DeviceProfile extends BaseData implements HasName, HasTenantId, HasOtaPackage, HasRuleEngineProfile, ExportableEntity, HasImage, HasDefaultOption, HasVersion { private static final long serialVersionUID = 6998485460273302018L; @@ -97,6 +97,7 @@ public class DeviceProfile extends BaseData implements HasName, private RuleChainId defaultEdgeRuleChainId; private DeviceProfileId externalId; + private Long version; public DeviceProfile() { super(); @@ -122,6 +123,7 @@ public class DeviceProfile extends BaseData implements HasName, this.softwareId = deviceProfile.getSoftwareId(); this.defaultEdgeRuleChainId = deviceProfile.getDefaultEdgeRuleChainId(); this.externalId = deviceProfile.getExternalId(); + this.version = deviceProfile.getVersion(); } @Schema(description = "JSON object with the device profile Id. " + 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 344045134e..8c7a89a220 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 @@ -36,7 +36,7 @@ import org.thingsboard.server.common.data.validation.NoXss; @AllArgsConstructor @EqualsAndHashCode(callSuper = true) public class EntityView extends BaseDataWithAdditionalInfo - implements HasName, HasTenantId, HasCustomerId, ExportableEntity { + implements HasName, HasTenantId, HasCustomerId, HasVersion, ExportableEntity { private static final long serialVersionUID = 5582010124562018986L; @@ -60,6 +60,7 @@ public class EntityView extends BaseDataWithAdditionalInfo private long endTimeMs; private EntityViewId externalId; + private Long version; public EntityView() { super(); @@ -80,6 +81,7 @@ public class EntityView extends BaseDataWithAdditionalInfo this.startTimeMs = entityView.getStartTimeMs(); this.endTimeMs = entityView.getEndTimeMs(); this.externalId = entityView.getExternalId(); + this.version = entityView.getVersion(); } @Schema(description = "JSON object with Customer Id. Use 'assignEntityViewToCustomer' to change the Customer Id.", accessMode = Schema.AccessMode.READ_ONLY) @@ -102,7 +104,7 @@ public class EntityView extends BaseDataWithAdditionalInfo @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." ) + "Omit this field to create new Entity View.") @Override public EntityViewId getId() { return super.getId(); @@ -114,7 +116,7 @@ public class EntityView extends BaseDataWithAdditionalInfo return super.getCreatedTime(); } - @Schema(description = "Additional parameters of the device",implementation = com.fasterxml.jackson.databind.JsonNode.class) + @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/HasVersion.java b/common/data/src/main/java/org/thingsboard/server/common/data/HasVersion.java index b9af6f93c9..db916d2195 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/HasVersion.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/HasVersion.java @@ -16,5 +16,10 @@ package org.thingsboard.server.common.data; public interface HasVersion { + Long getVersion(); + + default void setVersion(Long version) { + } + } 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 b7fade3e09..0c0c5c760a 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 @@ -20,6 +20,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.validation.Length; @@ -27,7 +29,7 @@ import org.thingsboard.server.common.data.validation.NoXss; @Schema @EqualsAndHashCode(callSuper = true) -public class Tenant extends ContactBased implements HasTenantId, HasTitle { +public class Tenant extends ContactBased implements HasTenantId, HasTitle, HasVersion { private static final long serialVersionUID = 8057243243859922101L; @@ -43,6 +45,9 @@ public class Tenant extends ContactBased implements HasTenantId, HasTi @Schema(description = "JSON object with Tenant Profile Id") private TenantProfileId tenantProfileId; + @Getter @Setter + private Long version; + public Tenant() { super(); } @@ -56,6 +61,7 @@ public class Tenant extends ContactBased implements HasTenantId, HasTi this.title = tenant.getTitle(); this.region = tenant.getRegion(); this.tenantProfileId = tenant.getTenantProfileId(); + this.version = tenant.getVersion(); } public String getTitle() { @@ -98,7 +104,7 @@ public class Tenant extends ContactBased implements HasTenantId, HasTi @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." ) + "Omit this field to create new tenant.") @Override public TenantId getId() { return super.getId(); @@ -158,7 +164,7 @@ public class Tenant extends ContactBased implements HasTenantId, HasTi return super.getEmail(); } - @Schema(description = "Additional parameters of the device",implementation = com.fasterxml.jackson.databind.JsonNode.class) + @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/User.java b/common/data/src/main/java/org/thingsboard/server/common/data/User.java index 678b7cdac6..7b616d2e54 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 @@ -20,6 +20,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; @@ -33,7 +35,7 @@ import static org.apache.commons.lang3.StringUtils.isNotEmpty; @Schema @EqualsAndHashCode(callSuper = true) -public class User extends BaseDataWithAdditionalInfo implements HasName, HasTenantId, HasCustomerId, NotificationRecipient { +public class User extends BaseDataWithAdditionalInfo implements HasName, HasTenantId, HasCustomerId, NotificationRecipient, HasVersion { private static final long serialVersionUID = 8250339805336035966L; @@ -50,6 +52,9 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, @NoXss private String phone; + @Getter @Setter + private Long version; + public User() { super(); } @@ -67,6 +72,7 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, this.firstName = user.getFirstName(); this.lastName = user.getLastName(); this.phone = user.getPhone(); + this.version = user.getVersion(); } @@ -222,4 +228,5 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, public boolean isCustomerUser() { return !isSystemAdmin() && !isTenantAdmin(); } + } 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 16518bc618..4b79752135 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 @@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.ExportableEntity; import org.thingsboard.server.common.data.HasCustomerId; import org.thingsboard.server.common.data.HasLabel; import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.HasVersion; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.CustomerId; @@ -36,7 +37,7 @@ import java.util.Optional; @Schema @EqualsAndHashCode(callSuper = true) -public class Asset extends BaseDataWithAdditionalInfo implements HasLabel, HasTenantId, HasCustomerId, ExportableEntity { +public class Asset extends BaseDataWithAdditionalInfo implements HasLabel, HasTenantId, HasCustomerId, HasVersion, ExportableEntity { private static final long serialVersionUID = 2807343040519543363L; @@ -56,6 +57,8 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab @Getter @Setter private AssetId externalId; + @Getter @Setter + private Long version; public Asset() { super(); @@ -74,6 +77,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.label = asset.getLabel(); this.assetProfileId = asset.getAssetProfileId(); this.externalId = asset.getExternalId(); + this.version = asset.getVersion(); } public void update(Asset asset) { @@ -85,6 +89,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.assetProfileId = asset.getAssetProfileId(); Optional.ofNullable(asset.getAdditionalInfo()).ifPresent(this::setAdditionalInfo); this.externalId = asset.getExternalId(); + this.version = asset.getVersion(); } @Schema(description = "JSON object with the asset Id. " + 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 91563c0f2d..890c497d4b 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 @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.HasImage; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasRuleEngineProfile; import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.HasVersion; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.RuleChainId; @@ -39,7 +40,7 @@ import org.thingsboard.server.common.data.validation.NoXss; @ToString(exclude = {"image"}) @EqualsAndHashCode(callSuper = true) @Slf4j -public class AssetProfile extends BaseData implements HasName, HasTenantId, HasRuleEngineProfile, ExportableEntity, HasImage, HasDefaultOption { +public class AssetProfile extends BaseData implements HasName, HasTenantId, HasRuleEngineProfile, ExportableEntity, HasImage, HasDefaultOption, HasVersion { private static final long serialVersionUID = 6998485460273302018L; @@ -74,6 +75,7 @@ public class AssetProfile extends BaseData implements HasName, H private RuleChainId defaultEdgeRuleChainId; private AssetProfileId externalId; + private Long version; public AssetProfile() { super(); @@ -95,6 +97,7 @@ public class AssetProfile extends BaseData implements HasName, H this.defaultQueueName = assetProfile.getDefaultQueueName(); this.defaultEdgeRuleChainId = assetProfile.getDefaultEdgeRuleChainId(); this.externalId = assetProfile.getExternalId(); + this.version = assetProfile.getVersion(); } @Schema(description = "JSON object with the asset profile Id. " + 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 67d32d6e89..ec8ade7f69 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 @@ -17,12 +17,14 @@ package org.thingsboard.server.common.data.edge; import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.Setter; import lombok.ToString; import org.thingsboard.server.common.data.BaseDataWithAdditionalInfo; import org.thingsboard.server.common.data.HasCustomerId; import org.thingsboard.server.common.data.HasLabel; import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.HasVersion; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.RuleChainId; @@ -34,7 +36,7 @@ import org.thingsboard.server.common.data.validation.NoXss; @EqualsAndHashCode(callSuper = true) @ToString @Setter -public class Edge extends BaseDataWithAdditionalInfo implements HasLabel, HasTenantId, HasCustomerId { +public class Edge extends BaseDataWithAdditionalInfo implements HasLabel, HasTenantId, HasCustomerId, HasVersion { private static final long serialVersionUID = 4934987555236873728L; @@ -57,6 +59,9 @@ public class Edge extends BaseDataWithAdditionalInfo implements HasLabel @Length(fieldName = "secret") private String secret; + @Getter + private Long version; + public Edge() { super(); } @@ -75,6 +80,7 @@ public class Edge extends BaseDataWithAdditionalInfo implements HasLabel this.name = edge.getName(); this.routingKey = edge.getRoutingKey(); this.secret = edge.getSecret(); + this.version = edge.getVersion(); } public void update(Edge edge) { @@ -86,6 +92,7 @@ public class Edge extends BaseDataWithAdditionalInfo implements HasLabel this.name = edge.getName(); this.routingKey = edge.getRoutingKey(); this.secret = edge.getSecret(); + this.version = edge.getVersion(); } @Schema(description = "JSON object with the Edge Id. " + 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 7bee0c6094..176de62f69 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 @@ -43,7 +43,7 @@ public enum EdgeEventActionType { DELETED_COMMENT(ActionType.DELETED_COMMENT), ASSIGNED_TO_EDGE(ActionType.ASSIGNED_TO_EDGE), UNASSIGNED_FROM_EDGE(ActionType.UNASSIGNED_FROM_EDGE), - CREDENTIALS_REQUEST(null), + CREDENTIALS_REQUEST(null), // deprecated ENTITY_MERGE_REQUEST(null); // deprecated private final ActionType actionType; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java b/common/data/src/main/java/org/thingsboard/server/common/data/exception/EntityVersionMismatchException.java similarity index 72% rename from dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java rename to common/data/src/main/java/org/thingsboard/server/common/data/exception/EntityVersionMismatchException.java index 3b9aa3d5c1..310c6bccf7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventCleanupRepository.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/exception/EntityVersionMismatchException.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao.sql.event; +package org.thingsboard.server.common.data.exception; -public interface EventCleanupRepository { +public class EntityVersionMismatchException extends RuntimeException { - void cleanupEvents(long eventExpTime, boolean debug); + public EntityVersionMismatchException(String message, Throwable cause) { + super(message, cause); + } - void migrateEvents(long regularEventTs, long debugEventTs); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java index 0f789a5822..43423e9eef 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java @@ -29,6 +29,7 @@ public enum ThingsboardErrorCode { ITEM_NOT_FOUND(32), TOO_MANY_REQUESTS(33), TOO_MANY_UPDATES(34), + VERSION_CONFLICT(35), SUBSCRIPTION_VIOLATION(40), PASSWORD_VIOLATION(45); 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 7aa472bea1..6532a4fe0d 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 @@ -42,7 +42,8 @@ public enum LimitedApi { TRANSPORT_MESSAGES_PER_DEVICE("transport messages per device", false), TRANSPORT_MESSAGES_PER_GATEWAY("transport messages per gateway", false), TRANSPORT_MESSAGES_PER_GATEWAY_DEVICE("transport messages per gateway device", false), - EMAILS("emails sending", true); + EMAILS("emails sending", true), + WS_SUBSCRIPTIONS("WS subscriptions", false); private Function configExtractor; @Getter 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 5448fcd259..0f7e793878 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 @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.ExportableEntity; import org.thingsboard.server.common.data.HasDefaultOption; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.HasVersion; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.TenantId; @@ -36,7 +37,7 @@ import org.thingsboard.server.common.data.validation.NoXss; @Data @EqualsAndHashCode(callSuper = true) @Slf4j -public class RuleChain extends BaseDataWithAdditionalInfo implements HasName, HasTenantId, ExportableEntity, HasDefaultOption { +public class RuleChain extends BaseDataWithAdditionalInfo implements HasName, HasTenantId, ExportableEntity, HasDefaultOption, HasVersion { private static final long serialVersionUID = -5656679015121935465L; @@ -58,6 +59,7 @@ public class RuleChain extends BaseDataWithAdditionalInfo implement private transient JsonNode configuration; private RuleChainId externalId; + private Long version; @JsonIgnore private byte[] configurationBytes; @@ -79,6 +81,7 @@ public class RuleChain extends BaseDataWithAdditionalInfo implement this.root = ruleChain.isRoot(); this.setConfiguration(ruleChain.getConfiguration()); this.setExternalId(ruleChain.getExternalId()); + this.version = ruleChain.getVersion(); } @Override @@ -89,7 +92,7 @@ public class RuleChain extends BaseDataWithAdditionalInfo implement @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." ) + "Omit this field to create new rule chain.") @Override public RuleChainId getId() { return super.getId(); 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 e269f0438d..094582f647 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 @@ -17,20 +17,26 @@ package org.thingsboard.server.common.data.security; import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; import org.thingsboard.server.common.data.BaseData; +import org.thingsboard.server.common.data.HasVersion; import org.thingsboard.server.common.data.id.DeviceCredentialsId; import org.thingsboard.server.common.data.id.DeviceId; @Schema @EqualsAndHashCode(callSuper = true) -public class DeviceCredentials extends BaseData implements DeviceCredentialsFilter { +public class DeviceCredentials extends BaseData implements DeviceCredentialsFilter, HasVersion { private static final long serialVersionUID = -7869261127032877765L; private DeviceId deviceId; private DeviceCredentialsType credentialsType; private String credentialsId; private String credentialsValue; - + + @Getter @Setter + private Long version; + public DeviceCredentials() { super(); } @@ -45,6 +51,7 @@ public class DeviceCredentials extends BaseData implements this.credentialsType = deviceCredentials.getCredentialsType(); this.credentialsId = deviceCredentials.getCredentialsId(); this.credentialsValue = deviceCredentials.getCredentialsValue(); + this.version = deviceCredentials.getVersion(); } @Schema(requiredMode = Schema.RequiredMode.REQUIRED, accessMode = Schema.AccessMode.READ_ONLY, description = "The Id is automatically generated during device creation. " + @@ -111,4 +118,5 @@ public class DeviceCredentials extends BaseData implements + credentialsId + ", credentialsValue=" + credentialsValue + ", createdTime=" + createdTime + ", id=" + id + "]"; } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java index 4ec88fd92b..1b5459ec1a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java @@ -60,6 +60,6 @@ import java.lang.annotation.Target; @Type(name = "NOTIFICATION_RULE", value = NotificationRule.class), @Type(name = "TB_RESOURCE", value = TbResource.class) }) -@JsonIgnoreProperties(value = {"tenantId", "createdTime"}, ignoreUnknown = true) +@JsonIgnoreProperties(value = {"tenantId", "createdTime", "version"}, ignoreUnknown = true) public @interface JsonTbEntity { } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/DeviceExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/DeviceExportData.java index ec922f2362..3285fd4ca0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/DeviceExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/DeviceExportData.java @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; public class DeviceExportData extends EntityExportData { @JsonProperty(index = 3) - @JsonIgnoreProperties({"id", "deviceId", "createdTime"}) + @JsonIgnoreProperties({"id", "deviceId", "createdTime", "version"}) private DeviceCredentials credentials; @JsonIgnore diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/EntityExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/EntityExportData.java index 2336c283a6..7f60ea5bb7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/EntityExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/EntityExportData.java @@ -95,4 +95,5 @@ public class EntityExportData> { public boolean hasRelations() { return relations != null; } + } 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 6a73e61d96..36692f5738 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 @@ -17,16 +17,19 @@ package org.thingsboard.server.common.data.widget; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.HasVersion; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; @Data -public class BaseWidgetType extends BaseData implements HasName, HasTenantId { +@EqualsAndHashCode(callSuper = true) +public class BaseWidgetType extends BaseData implements HasName, HasTenantId, HasVersion { private static final long serialVersionUID = 8388684344603660756L; @@ -47,6 +50,8 @@ public class BaseWidgetType extends BaseData implements HasName, H @Schema(description = "Whether widget type is SCADA symbol.", example = "true") private boolean scada; + private Long version; + public BaseWidgetType() { super(); } @@ -62,12 +67,13 @@ public class BaseWidgetType extends BaseData implements HasName, H this.name = widgetType.getName(); this.deprecated = widgetType.isDeprecated(); this.scada = widgetType.isScada(); + this.version = widgetType.getVersion(); } @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." ) + "Omit this field to create new Widget Type.") @Override public WidgetTypeId getId() { return super.getId(); @@ -78,4 +84,5 @@ public class BaseWidgetType extends BaseData implements HasName, H public long getCreatedTime() { return super.getCreatedTime(); } + } 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 f29fe8fec5..55bd1cf27a 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 @@ -18,8 +18,7 @@ package org.thingsboard.server.common.data.widget; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.Getter; -import lombok.Setter; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.ExportableEntity; import org.thingsboard.server.common.data.HasImage; import org.thingsboard.server.common.data.HasName; @@ -29,7 +28,8 @@ import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; @Data -@JsonPropertyOrder({ "fqn", "name", "deprecated", "image", "description", "descriptor", "externalId" }) +@EqualsAndHashCode(callSuper = true) +@JsonPropertyOrder({"fqn", "name", "deprecated", "image", "description", "descriptor", "externalId"}) public class WidgetTypeDetails extends WidgetType implements HasName, HasTenantId, HasImage, ExportableEntity { @Schema(description = "Relative or external image URL. Replaced with image data URL (Base64) in case of relative URL and 'inlineImages' option enabled.") @@ -42,8 +42,6 @@ public class WidgetTypeDetails extends WidgetType implements HasName, HasTenantI @Schema(description = "Tags of the widget type") private String[] tags; - @Getter - @Setter private WidgetTypeId externalId; public WidgetTypeDetails() { @@ -65,4 +63,5 @@ public class WidgetTypeDetails extends WidgetType implements HasName, HasTenantI this.tags = widgetTypeDetails.getTags(); this.externalId = widgetTypeDetails.getExternalId(); } + } 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 c5cc61d583..005e4ca252 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 @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.HasImage; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.HasTitle; +import org.thingsboard.server.common.data.HasVersion; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.validation.Length; @@ -33,7 +34,7 @@ import org.thingsboard.server.common.data.validation.NoXss; @Schema @EqualsAndHashCode(callSuper = true) -public class WidgetsBundle extends BaseData implements HasName, HasTenantId, ExportableEntity, HasTitle, HasImage { +public class WidgetsBundle extends BaseData implements HasName, HasTenantId, ExportableEntity, HasTitle, HasImage, HasVersion { private static final long serialVersionUID = -7627368878362410489L; @@ -81,6 +82,9 @@ public class WidgetsBundle extends BaseData implements HasName, @Getter @Setter private WidgetsBundleId externalId; + @Getter + @Setter + private Long version; public WidgetsBundle() { super(); @@ -100,6 +104,7 @@ public class WidgetsBundle extends BaseData implements HasName, this.description = widgetsBundle.getDescription(); this.order = widgetsBundle.getOrder(); this.externalId = widgetsBundle.getExternalId(); + this.version = widgetsBundle.getVersion(); } @Schema(description = "JSON object with the Widget Bundle Id. " + diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/FromEdgeSyncResponse.java b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/FromEdgeSyncResponse.java index 733129b4de..baf483310c 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/edge/FromEdgeSyncResponse.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/edge/FromEdgeSyncResponse.java @@ -25,12 +25,13 @@ import java.util.UUID; @Data public class FromEdgeSyncResponse implements EdgeSessionMsg { - private static final long serialVersionUID = -6360890886315347486L; + private static final long serialVersionUID = -6360890556315667486L; private final UUID id; private final TenantId tenantId; private final EdgeId edgeId; private final boolean success; + private final String error; @Override public MsgType getMsgType() { diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/tools/MaxPayloadSizeExceededException.java b/common/message/src/main/java/org/thingsboard/server/common/msg/tools/MaxPayloadSizeExceededException.java index 8195bf19a7..a9a206a4df 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/tools/MaxPayloadSizeExceededException.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/tools/MaxPayloadSizeExceededException.java @@ -20,4 +20,5 @@ public class MaxPayloadSizeExceededException extends RuntimeException { public MaxPayloadSizeExceededException() { super("Payload size exceeds the limit"); } + } diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimitsException.java b/common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimitsException.java index b39477fa38..32d55048ae 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimitsException.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimitsException.java @@ -30,4 +30,10 @@ public class TbRateLimitsException extends AbstractRateLimitException { super(entityType.name() + " rate limits reached!"); this.entityType = entityType; } + + public TbRateLimitsException(String message) { + super(message); + this.entityType = null; + } + } diff --git a/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java b/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java index a7c5d5185e..5646a37a68 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java @@ -17,9 +17,7 @@ package org.thingsboard.server.common.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.protobuf.ByteString; -import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.Nullable; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.ApiUsageStateValue; @@ -162,6 +160,7 @@ public class ProtoUtils { .setEdgeIdMSB(response.getEdgeId().getId().getMostSignificantBits()) .setEdgeIdLSB(response.getEdgeId().getId().getLeastSignificantBits()) .setSuccess(response.isSuccess()) + .setError(response.getError()) .build(); } @@ -170,7 +169,8 @@ public class ProtoUtils { new UUID(proto.getResponseIdMSB(), proto.getResponseIdLSB()), TenantId.fromUUID(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())), new EdgeId(new UUID(proto.getEdgeIdMSB(), proto.getEdgeIdLSB())), - proto.getSuccess() + proto.getSuccess(), + proto.getError() ); } @@ -568,6 +568,9 @@ public class ProtoUtils { if (isNotNull(device.getDeviceDataBytes())) { builder.setDeviceData(ByteString.copyFrom(device.getDeviceDataBytes())); } + if (isNotNull(device.getVersion())) { + builder.setVersion(device.getVersion()); + } return builder.build(); } @@ -599,6 +602,9 @@ public class ProtoUtils { if (proto.hasDeviceData()) { device.setDeviceDataBytes(proto.getDeviceData().toByteArray()); } + if (proto.hasVersion()) { + device.setVersion(proto.getVersion()); + } return device; } @@ -654,6 +660,9 @@ public class ProtoUtils { builder.setDefaultEdgeRuleChainIdMSB(getMsb(deviceProfile.getDefaultEdgeRuleChainId())) .setDefaultEdgeRuleChainIdLSB(getLsb(deviceProfile.getDefaultEdgeRuleChainId())); } + if (isNotNull(deviceProfile.getVersion())) { + builder.setVersion(deviceProfile.getVersion()); + } return builder.build(); } @@ -699,6 +708,9 @@ public class ProtoUtils { if (proto.hasDefaultEdgeRuleChainIdMSB() && proto.hasDefaultEdgeRuleChainIdLSB()) { deviceProfile.setDefaultEdgeRuleChainId(getEntityId(proto.getDefaultEdgeRuleChainIdMSB(), proto.getDefaultEdgeRuleChainIdLSB(), RuleChainId::new)); } + if (proto.hasVersion()) { + deviceProfile.setVersion(proto.getVersion()); + } return deviceProfile; } @@ -741,6 +753,9 @@ public class ProtoUtils { if (isNotNull(tenant.getAdditionalInfo())) { builder.setAdditionalInfo(JacksonUtil.toString(tenant.getAdditionalInfo())); } + if (isNotNull(tenant.getVersion())) { + builder.setVersion(tenant.getVersion()); + } return builder.build(); } @@ -780,6 +795,9 @@ public class ProtoUtils { if (proto.hasAdditionalInfo()) { tenant.setAdditionalInfo(JacksonUtil.toJsonNode(proto.getAdditionalInfo())); } + if (proto.hasVersion()) { + tenant.setVersion(proto.getVersion()); + } return tenant; } @@ -994,6 +1012,9 @@ public class ProtoUtils { if (deviceCredentials.getCredentialsValue() != null) { builder.setCredentialsValue(deviceCredentials.getCredentialsValue()); } + if (deviceCredentials.getVersion() != null) { + builder.setVersion(deviceCredentials.getVersion()); + } return builder.build(); } @@ -1005,6 +1026,7 @@ public class ProtoUtils { deviceCredentials.setCredentialsId(proto.getCredentialsId()); deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(proto.getCredentialsType().name())); deviceCredentials.setCredentialsValue(proto.hasCredentialsValue() ? proto.getCredentialsValue() : null); + deviceCredentials.setVersion(proto.hasVersion() ? proto.getVersion() : null); return deviceCredentials; } diff --git a/common/proto/src/main/proto/queue.proto b/common/proto/src/main/proto/queue.proto index 2b715d71af..7c3bfddc08 100644 --- a/common/proto/src/main/proto/queue.proto +++ b/common/proto/src/main/proto/queue.proto @@ -217,6 +217,7 @@ message DeviceProto { optional int64 softwareIdLSB = 18; optional int64 externalIdMSB = 19; optional int64 externalIdLSB = 20; + optional int64 version = 21; } message DeviceProfileProto { @@ -247,6 +248,7 @@ message DeviceProfileProto { optional int64 defaultEdgeRuleChainIdLSB = 25; optional int64 externalIdMSB = 26; optional int64 externalIdLSB = 27; + optional int64 version = 28; } message TenantProto { @@ -266,6 +268,7 @@ message TenantProto { optional string phone = 14; optional string email = 15; optional string additionalInfo = 16; + optional int64 version = 17; } message TenantProfileProto { @@ -677,6 +680,7 @@ message DeviceCredentialsProto { CredentialsType credentialsType = 6; string credentialsId = 7; optional string credentialsValue = 8; + optional int64 version = 9; } message CredentialsDataProto { @@ -1157,6 +1161,7 @@ message FromEdgeSyncResponseMsgProto { int64 edgeIdMSB = 5; int64 edgeIdLSB = 6; bool success = 7; + string error = 8; } message DeviceEdgeUpdateMsgProto { diff --git a/common/proto/src/test/java/org/thingsboard/server/common/util/ProtoUtilsTest.java b/common/proto/src/test/java/org/thingsboard/server/common/util/ProtoUtilsTest.java index 904e85f702..a513d3e311 100644 --- a/common/proto/src/test/java/org/thingsboard/server/common/util/ProtoUtilsTest.java +++ b/common/proto/src/test/java/org/thingsboard/server/common/util/ProtoUtilsTest.java @@ -124,7 +124,7 @@ class ProtoUtilsTest { @Test void protoFromEdgeSyncResponseSerialization() { - FromEdgeSyncResponse msg = new FromEdgeSyncResponse(id, tenantId, edgeId, true); + FromEdgeSyncResponse msg = new FromEdgeSyncResponse(id, tenantId, edgeId, true, "Error Msg"); assertThat(ProtoUtils.fromProto(ProtoUtils.toProto(msg))).as("deserialized").isEqualTo(msg); } 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 2bcb5461e1..1ba7c9aff1 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 @@ -39,8 +39,8 @@ import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.coap.ConfigProtos; import org.thingsboard.server.gen.transport.coap.DeviceInfoProtos; -import org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos; import org.thingsboard.server.gen.transport.coap.MeasurementsProtos; +import org.thingsboard.server.gen.transport.coap.MeasurementsProtos.ProtoChannel; import org.thingsboard.server.transport.coap.AbstractCoapTransportResource; import org.thingsboard.server.transport.coap.CoapTransportContext; import org.thingsboard.server.transport.coap.callback.CoapDeviceAuthCallback; @@ -49,19 +49,21 @@ import org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils; import java.nio.ByteBuffer; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import static com.google.gson.JsonParser.parseString; import static org.thingsboard.server.transport.coap.CoapTransportService.CONFIGURATION; import static org.thingsboard.server.transport.coap.CoapTransportService.CURRENT_TIMESTAMP; import static org.thingsboard.server.transport.coap.CoapTransportService.DEVICE_INFO; import static org.thingsboard.server.transport.coap.CoapTransportService.MEASUREMENTS; +import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.isBinarySensor; +import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.isSensorError; @Slf4j public class CoapEfentoTransportResource extends AbstractCoapTransportResource { @@ -220,127 +222,186 @@ public class CoapEfentoTransportResource extends AbstractCoapTransportResource { } } - private List getEfentoMeasurements(MeasurementsProtos.ProtoMeasurements protoMeasurements, UUID sessionId) { + List getEfentoMeasurements(MeasurementsProtos.ProtoMeasurements protoMeasurements, UUID sessionId) { String serialNumber = CoapEfentoUtils.convertByteArrayToString(protoMeasurements.getSerialNum().toByteArray()); boolean batteryStatus = protoMeasurements.getBatteryStatus(); int measurementPeriodBase = protoMeasurements.getMeasurementPeriodBase(); int measurementPeriodFactor = protoMeasurements.getMeasurementPeriodFactor(); int signal = protoMeasurements.getSignal(); - List channelsList = protoMeasurements.getChannelsList(); + long nextTransmissionAtMillis = TimeUnit.SECONDS.toMillis(protoMeasurements.getNextTransmissionAt()); + + List channelsList = protoMeasurements.getChannelsList(); + if (CollectionUtils.isEmpty(channelsList)) { + throw new IllegalStateException("[" + sessionId + "]: Failed to get Efento measurements, reason: channels list is empty!"); + } + Map valuesMap = new TreeMap<>(); - if (!CollectionUtils.isEmpty(channelsList)) { - int channel = 0; - JsonObject values; - for (MeasurementsProtos.ProtoChannel protoChannel : channelsList) { - channel++; - boolean isBinarySensor = false; - MeasurementTypeProtos.MeasurementType measurementType = protoChannel.getType(); - String measurementTypeName = measurementType.name(); - if (measurementType.equals(MeasurementTypeProtos.MeasurementType.OK_ALARM) - || measurementType.equals(MeasurementTypeProtos.MeasurementType.FLOODING)) { - isBinarySensor = true; - } - if (measurementPeriodFactor == 0 && isBinarySensor) { - measurementPeriodFactor = 14; - } else { - measurementPeriodFactor = 1; + for (int channel = 0; channel < channelsList.size(); channel++) { + ProtoChannel protoChannel = channelsList.get(channel); + List sampleOffsetsList = protoChannel.getSampleOffsetsList(); + if (CollectionUtils.isEmpty(sampleOffsetsList)) { + log.trace("[{}][{}] sampleOffsetsList list is empty!", sessionId, protoChannel.getType().name()); + continue; + } + boolean isBinarySensor = isBinarySensor(protoChannel.getType()); + int channelPeriodFactor = (measurementPeriodFactor == 0 ? (isBinarySensor ? 14 : 1) : measurementPeriodFactor); + int measurementPeriod = measurementPeriodBase * channelPeriodFactor; + long measurementPeriodMillis = TimeUnit.SECONDS.toMillis(measurementPeriod); + long startTimestampMillis = TimeUnit.SECONDS.toMillis(protoChannel.getTimestamp()); + + for (int i = 0; i < sampleOffsetsList.size(); i++) { + int sampleOffset = sampleOffsetsList.get(i); + if (isSensorError(sampleOffset)) { + log.warn("[{}],[{}] Sensor error value! Ignoring.", sessionId, sampleOffset); + continue; } - int measurementPeriod = measurementPeriodBase * measurementPeriodFactor; - long measurementPeriodMillis = TimeUnit.SECONDS.toMillis(measurementPeriod); - long nextTransmissionAtMillis = TimeUnit.SECONDS.toMillis(protoMeasurements.getNextTransmissionAt()); - int startPoint = protoChannel.getStartPoint(); - int startTimestamp = protoChannel.getTimestamp(); - long startTimestampMillis = TimeUnit.SECONDS.toMillis(startTimestamp); - List sampleOffsetsList = protoChannel.getSampleOffsetsList(); - if (!CollectionUtils.isEmpty(sampleOffsetsList)) { - int sampleOfssetsListSize = sampleOffsetsList.size(); - for (int i = 0; i < sampleOfssetsListSize; i++) { - int sampleOffset = sampleOffsetsList.get(i); - Integer previousSampleOffset = isBinarySensor && i > 0 ? sampleOffsetsList.get(i - 1) : null; - if (sampleOffset == -32768) { - log.warn("[{}],[{}] Sensor error value! Ignoring.", sessionId, sampleOffset); - } else { - switch (measurementType) { - case TEMPERATURE: - values = valuesMap.computeIfAbsent(startTimestampMillis, k -> - CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); - values.addProperty("temperature_" + channel, ((double) (startPoint + sampleOffset)) / 10f); - startTimestampMillis = startTimestampMillis + measurementPeriodMillis; - break; - case WATER_METER: - values = valuesMap.computeIfAbsent(startTimestampMillis, k -> - CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); - values.addProperty("pulse_counter_water_" + channel, ((double) (startPoint + sampleOffset))); - startTimestampMillis = startTimestampMillis + measurementPeriodMillis; - break; - case HUMIDITY: - values = valuesMap.computeIfAbsent(startTimestampMillis, k -> - CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); - values.addProperty("humidity_" + channel, (double) (startPoint + sampleOffset)); - startTimestampMillis = startTimestampMillis + measurementPeriodMillis; - break; - case ATMOSPHERIC_PRESSURE: - values = valuesMap.computeIfAbsent(startTimestampMillis, k -> - CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); - values.addProperty("pressure_" + channel, (double) (startPoint + sampleOffset) / 10f); - startTimestampMillis = startTimestampMillis + measurementPeriodMillis; - break; - case DIFFERENTIAL_PRESSURE: - values = valuesMap.computeIfAbsent(startTimestampMillis, k -> - CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); - values.addProperty("pressure_diff_" + channel, (double) (startPoint + sampleOffset)); - startTimestampMillis = startTimestampMillis + measurementPeriodMillis; - break; - case OK_ALARM: - boolean currentIsOk = sampleOffset < 0; - if (previousSampleOffset != null) { - boolean previousIsOk = previousSampleOffset < 0; - boolean isOk = previousIsOk && currentIsOk; - boolean isAlarm = !previousIsOk && !currentIsOk; - if (isOk || isAlarm) { - break; - } - } - String data = currentIsOk ? "OK" : "ALARM"; - long sampleOffsetMillis = TimeUnit.SECONDS.toMillis(sampleOffset); - long measurementTimestamp = startTimestampMillis + Math.abs(sampleOffsetMillis); - values = valuesMap.computeIfAbsent(measurementTimestamp - 1000, k -> - CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); - values.addProperty("ok_alarm_" + channel, data); - break; - case PULSE_CNT: - values = valuesMap.computeIfAbsent(startTimestampMillis, k -> - CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); - values.addProperty("pulse_cnt_" + channel, (double) (startPoint + sampleOffset)); - startTimestampMillis = startTimestampMillis + measurementPeriodMillis; - break; - case NO_SENSOR: - case UNRECOGNIZED: - log.trace("[{}][{}] Sensor error value! Ignoring.", sessionId, measurementTypeName); - break; - default: - log.trace("[{}],[{}] Unsupported measurementType! Ignoring.", sessionId, measurementTypeName); - break; - } + + JsonObject values; + if (isBinarySensor) { + boolean currentIsOk = sampleOffset < 0; + Integer previousSampleOffset = i > 0 ? sampleOffsetsList.get(i - 1) : null; + if (previousSampleOffset != null) { //compare with previous value + boolean previousIsOk = previousSampleOffset < 0; + if (currentIsOk == previousIsOk) { + break; } } + long sampleOffsetMillis = TimeUnit.SECONDS.toMillis(sampleOffset); + long measurementTimestamp = startTimestampMillis + Math.abs(sampleOffsetMillis); + values = valuesMap.computeIfAbsent(measurementTimestamp - 1000, k -> + CoapEfentoUtils.setDefaultMeasurements(serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); + addBinarySample(protoChannel, currentIsOk, values, channel + 1, sessionId); } else { - log.trace("[{}][{}] sampleOffsetsList list is empty!", sessionId, measurementTypeName); + long timestampMillis = startTimestampMillis + i * measurementPeriodMillis; + values = valuesMap.computeIfAbsent(timestampMillis, k -> CoapEfentoUtils.setDefaultMeasurements( + serialNumber, batteryStatus, measurementPeriod, nextTransmissionAtMillis, signal, k)); + addContinuesSample(protoChannel, sampleOffset, values, channel + 1, sessionId); } } - } else { - throw new IllegalStateException("[" + sessionId + "]: Failed to get Efento measurements, reason: channels list is empty!"); } - if (!CollectionUtils.isEmpty(valuesMap)) { - List efentoMeasurements = new ArrayList<>(); - for (Long ts : valuesMap.keySet()) { - EfentoTelemetry measurement = new EfentoTelemetry(ts, valuesMap.get(ts)); - efentoMeasurements.add(measurement); - } - return efentoMeasurements; - } else { + + if (CollectionUtils.isEmpty(valuesMap)) { throw new IllegalStateException("[" + sessionId + "]: Failed to collect Efento measurements, reason, values map is empty!"); } + + return valuesMap.entrySet().stream() + .map(entry -> new EfentoTelemetry(entry.getKey(), entry.getValue())) + .collect(Collectors.toList()); + } + + private void addContinuesSample(ProtoChannel protoChannel, int sampleOffset, JsonObject values, int channelNumber, UUID sessionId) { + int startPoint = protoChannel.getStartPoint(); + + switch (protoChannel.getType()) { + case MEASUREMENT_TYPE_TEMPERATURE: + values.addProperty("temperature_" + channelNumber, ((double) (startPoint + sampleOffset)) / 10f); + break; + case MEASUREMENT_TYPE_WATER_METER: + values.addProperty("pulse_counter_water_" + channelNumber, ((double) (startPoint + sampleOffset))); + break; + case MEASUREMENT_TYPE_HUMIDITY: + values.addProperty("humidity_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_ATMOSPHERIC_PRESSURE: + values.addProperty("pressure_" + channelNumber, (double) (startPoint + sampleOffset) / 10f); + break; + case MEASUREMENT_TYPE_DIFFERENTIAL_PRESSURE: + values.addProperty("pressure_diff_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_PULSE_CNT: + values.addProperty("pulse_cnt_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_IAQ: + values.addProperty("iaq_" + channelNumber, (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_ELECTRICITY_METER: + values.addProperty("watt_hour_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_SOIL_MOISTURE: + values.addProperty("soil_moisture_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_AMBIENT_LIGHT: + values.addProperty("ambient_light_" + channelNumber, (double) (startPoint + sampleOffset) / 10f); + break; + case MEASUREMENT_TYPE_HIGH_PRESSURE: + values.addProperty("high_pressure_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_DISTANCE_MM: + values.addProperty("distance_mm_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_WATER_METER_ACC_MINOR: + values.addProperty("acc_counter_water_minor_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_WATER_METER_ACC_MAJOR: + values.addProperty("acc_counter_water_major_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_HUMIDITY_ACCURATE: + values.addProperty("humidity_relative_" + channelNumber, (double) (startPoint + sampleOffset) / 10f); + break; + case MEASUREMENT_TYPE_STATIC_IAQ: + values.addProperty("static_iaq_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_CO2_EQUIVALENT: + values.addProperty("co2_ppm_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_BREATH_VOC: + values.addProperty("breath_voc_ppm_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_PERCENTAGE: + values.addProperty("percentage_" + channelNumber, (double) (startPoint + sampleOffset) / 100f); + break; + case MEASUREMENT_TYPE_VOLTAGE: + values.addProperty("voltage_" + channelNumber, (double) (startPoint + sampleOffset) / 10f); + break; + case MEASUREMENT_TYPE_CURRENT: + values.addProperty("current_" + channelNumber, (double) (startPoint + sampleOffset) / 100f); + break; + case MEASUREMENT_TYPE_PULSE_CNT_ACC_MINOR: + values.addProperty("pulse_cnt_minor_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_PULSE_CNT_ACC_MAJOR: + values.addProperty("pulse_cnt_major_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_ELEC_METER_ACC_MINOR: + values.addProperty("elec_meter_minor_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_ELEC_METER_ACC_MAJOR: + values.addProperty("elec_meter_major_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MINOR: + values.addProperty("pulse_cnt_wide_minor_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MAJOR: + values.addProperty("pulse_cnt_wide_major_" + channelNumber, (double) (startPoint + sampleOffset)); + break; + case MEASUREMENT_TYPE_CURRENT_PRECISE: + values.addProperty("current_precise_" + channelNumber, (double) (startPoint + sampleOffset)/1000f); + break; + case MEASUREMENT_TYPE_NO_SENSOR: + case UNRECOGNIZED: + log.trace("[{}][{}] Sensor error value! Ignoring.", sessionId, protoChannel.getType().name()); + break; + default: + log.trace("[{}],[{}] Unsupported measurementType! Ignoring.", sessionId, protoChannel.getType().name()); + break; + } + } + + private void addBinarySample(ProtoChannel protoChannel, boolean valueIsOk, JsonObject values, int channel, UUID sessionId) { + switch (protoChannel.getType()) { + case MEASUREMENT_TYPE_OK_ALARM: + values.addProperty("ok_alarm_" + channel, valueIsOk ? "OK" : "ALARM"); + break; + case MEASUREMENT_TYPE_FLOODING: + values.addProperty("flooding_" + channel, valueIsOk ? "OK" : "WATER_DETECTED"); + break; + case MEASUREMENT_TYPE_OUTPUT_CONTROL: + values.addProperty("output_control_" + channel, valueIsOk ? "OFF" : "ON"); + break; + default: + log.trace("[{}],[{}] Unsupported binary measurementType! Ignoring.", sessionId, protoChannel.getType().name()); + break; + } } private EfentoTelemetry getEfentoDeviceInfo(DeviceInfoProtos.ProtoDeviceInfo protoDeviceInfo) { diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/utils/CoapEfentoUtils.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/utils/CoapEfentoUtils.java index d87c97543e..96c1805be3 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/utils/CoapEfentoUtils.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/utils/CoapEfentoUtils.java @@ -16,11 +16,16 @@ package org.thingsboard.server.transport.coap.efento.utils; import com.google.gson.JsonObject; +import org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_FLOODING; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_OK_ALARM; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_OUTPUT_CONTROL; + public class CoapEfentoUtils { public static String convertByteArrayToString(byte[] a) { @@ -50,4 +55,12 @@ public class CoapEfentoUtils { return values; } + public static boolean isBinarySensor(MeasurementType type) { + return type == MEASUREMENT_TYPE_OK_ALARM || type == MEASUREMENT_TYPE_FLOODING || type == MEASUREMENT_TYPE_OUTPUT_CONTROL; + } + + public static boolean isSensorError(int sampleOffset) { + return sampleOffset >= 8355840 && sampleOffset <= 8388607; + } + } diff --git a/common/transport/coap/src/main/proto/efento/proto_config.proto b/common/transport/coap/src/main/proto/efento/proto_config.proto index 6212681403..25dbec883f 100644 --- a/common/transport/coap/src/main/proto/efento/proto_config.proto +++ b/common/transport/coap/src/main/proto/efento/proto_config.proto @@ -22,26 +22,13 @@ option java_package = "org.thingsboard.server.gen.transport.coap"; option java_outer_classname = "ConfigProtos"; /* Message containing optional channels control parameters */ -message ProtoChannelControl { +message ProtoOutputControlState { /* Channel index */ uint32 channel_index = 1; - /* Control parameters. Maximal number equals 4. This field is channel specific: */ - /* IO_control channel: */ - /* - control_params[0]: */ - /* - Byte 0: On state configuration */ - /* 0x01 - Low */ - /* 0x02 - High */ - /* 0x03 - High-Z (disconnected) */ - /* - Byte 1: Off state configuration */ - /* 0x01 - Low */ - /* 0x02 - High */ - /* 0x03 - High-Z (disconnected) */ - /* - Byte 2: Power on channel state */ - /* 0x01 - On */ - /* 0x02 - Off */ - repeated uint32 control_params = 2; + /* Channel state ON/OFF. Range (1 - OFF; 2 - ON) */ + uint32 channel_state = 2; } /* Message containing request data for accesing calibration parameters */ @@ -58,6 +45,39 @@ message ProtoCalibrationParameters { repeated int32 parameters = 3; } +enum BleAdvertisingPeriodMode { + + /* Invalid value */ + BLE_ADVERTISING_PERIOD_MODE_UNSPECIFIED = 0; + + /* Default behavior - faster advertising when measurement period is < 15s. */ + BLE_ADVERTISING_PERIOD_MODE_DEFAULT = 1; + + /* User-configured normal interval is used. */ + BLE_ADVERTISING_PERIOD_MODE_NORMAL = 2; + + /* User-configured fast interval is used. */ + BLE_ADVERTISING_PERIOD_MODE_FAST = 3; +} + +/* Message containing BLE advertising period configuration */ +message ProtoBleAdvertisingPeriod { + + /* BLE advertising mode: */ + /* - 1: Default, BLE advertising interval is set to 1022.5ms or some lower value, based on continuous measurement period. */ + /* - 2: Normal, uses user-configured value from 'normal' field. */ + /* - 3: Fast, uses user-configured value from 'fast' field (must be lower than or equal to 'normal' field). */ + BleAdvertisingPeriodMode mode = 1; + + /* BLE advertising interval when in normal mode, configured in 0.625ms steps. */ + /* Range: [32:16384] */ + uint32 normal = 2; + + /* BLE advertising interval when in fast mode, configured in 0.625ms steps. */ + /* Range: [32:16384] */ + uint32 fast = 3; +} + /* Main message sent in the payload. Each field in this message is independent of the others - only parameters that should be */ /* changed need to be sent in the payload. */ /* If the value of a selected parameter shall not be changed, do not include it in the payload */ @@ -115,16 +135,26 @@ message ProtoConfig { /* 65535 - disable transfer limit function */ uint32 transfer_limit_timer = 10; - /* Data (measurements) server IP address */ - /* IP of the data server as string in form x.x.x.x. For example: 18.184.24.239 */ + /* For firmware >= 6.07.00: */ + /* IP or URL address of the data (measurements) server */ + /* The IP or URL of the data server, provided as string with a maximum length of 31 characters */ + /* For example, use "18.184.24.239" for an IP address or "efento.test.io" for a URL */ + /* For firmware < 6.07.00: */ + /* IP address of the data (measurements) server */ + /* For example, use "18.184.24.239" */ string data_server_ip = 11; /* Data (measurements) server port */ /* Range: [1:65535] */ uint32 data_server_port = 12; - /* Update server IP address */ - /* IP of data server as string in form x.x.x.x. For example: 18.184.24.239 */ + /* For firmware >= 6.07.00: */ + /* IP or URL address of the update server */ + /* The IP or URL of the update server, provided as string with a maximum length of 31 characters */ + /* For example, use "18.184.24.239" for an IP address or "efento.test.io" for a URL */ + /* For firmware < 6.07.00: */ + /* IP address of the update server */ + /* For example, use "18.184.24.239" */ string update_server_ip = 13; /* Update server port for UDP transmission */ @@ -144,7 +174,8 @@ message ProtoConfig { /* 0xFFFFFFFF or 1000000 - automatic selection */ uint32 plmn_selection = 17; - /* Device will power off its cellular modem for requested number of seconds. Maximum number of seconds 604800 (7 days) */ + /* Device will power off its cellular modem for requested number of seconds. */ + /* Range: [60:604800] (1 minute : 7 days) */ /* This field is only sent by server */ uint32 disable_modem_request = 18; @@ -263,9 +294,8 @@ message ProtoConfig { /* Calendar configuration. Up to 6 calendars are supported */ repeated ProtoCalendar calendars = 47; - /* Control parameters for channels. Maximal number of requests equals 6 */ - /* This field is only sent by server */ - repeated ProtoChannelControl channels_control_request = 48; + /* DEPRECATED - Used for backward compatibility */ + reserved 48; /* Set/get calibration parameters for single channel. */ ProtoCalibrationParameters calibration_parameters_request = 49; @@ -295,7 +325,7 @@ message ProtoConfig { reserved 52, 53; /* Encryption key configuration. Sensor sends in this field two last bytes of SHA256 hash calculated from its current */ - /* encryption_key configuration. */ + /* encryption_key configuration. When encryption key is disabled one byte 0x7F (DEL) is sent. */ /* Max length: 16 bytes. */ /* 0x7F - encryption key disabled. */ bytes encryption_key = 54; @@ -309,4 +339,14 @@ message ProtoConfig { /* String with special character 0x7F (DEL) only indicates that automatic password is turn on */ /* Password can only be set to custom value if apn_user_name has been configured (is not automatic) */ string apn_password = 56; + + /* Reserved by versions above 06.20.00 */ + reserved 57; + + /* Control output state on channel pin. Maximal number of requests equals 3 */ + /* This field is only sent by server */ + repeated ProtoOutputControlState output_control_state_request = 58; + + /* BLE advertising period configuration. */ + ProtoBleAdvertisingPeriod ble_advertising_period = 59; } \ No newline at end of file diff --git a/common/transport/coap/src/main/proto/efento/proto_device_info.proto b/common/transport/coap/src/main/proto/efento/proto_device_info.proto index 791d01acd7..a0cb9bc2f2 100644 --- a/common/transport/coap/src/main/proto/efento/proto_device_info.proto +++ b/common/transport/coap/src/main/proto/efento/proto_device_info.proto @@ -106,6 +106,11 @@ message ProtoModem /* parameters[32] - Rx_time - [0.1s] - Range: [0:2147483647]. Unknown value: -1 */ /* parameters[33] - Tx_time - [0.1s] - Range: [0:2147483647]. Unknown value: -1 */ repeated sint32 parameters = 2; + + /* ICCID of inserted/soldered sim card. String up to 22 characters long. */ + /* 0x7F if sim card is not detected, empty (not sent) if device does not have modem. */ + /* This field is only sent by device */ + string sim_card_identification = 3; } message ProtoUpdateInfo @@ -115,16 +120,16 @@ message ProtoUpdateInfo uint32 timestamp = 1; /* Update status, possible values: */ - /* - 0x1 - No update yet */ - /* - 0x2 - No error */ - /* - 0x3 - UDP socekt error */ - /* - 0x4 - Hash error */ - /* - 0x5 - Missing packet error */ - /* - 0x6 - Invalid data error */ - /* - 0x7 - Sending timeout error */ - /* - 0x8 - No SW to update error */ - /* - 0x9 - Sending unexpected error */ - /* - 0x10 - Unexpected error */ + /* - 1 - No update yet */ + /* - 2 - No error */ + /* - 3 - UDP socekt error */ + /* - 4 - Hash error */ + /* - 5 - Missing packet error */ + /* - 6 - Invalid data error */ + /* - 7 - Sending timeout error */ + /* - 8 - No SW to update error */ + /* - 9 - Sending unexpected error */ + /* - 10 - Unexpected error */ uint32 status = 2; } diff --git a/common/transport/coap/src/main/proto/efento/proto_measurement_types.proto b/common/transport/coap/src/main/proto/efento/proto_measurement_types.proto index 66a6c95d09..98029bed51 100644 --- a/common/transport/coap/src/main/proto/efento/proto_measurement_types.proto +++ b/common/transport/coap/src/main/proto/efento/proto_measurement_types.proto @@ -19,79 +19,160 @@ option java_package = "org.thingsboard.server.gen.transport.coap"; option java_outer_classname = "MeasurementTypeProtos"; enum MeasurementType { - NO_SENSOR = 0; - - /* [°C] - Celsius degree. Resolution 0.1°C. Range [-273.2-4000.0]. Type: Continuous */ - TEMPERATURE = 1; - - /* [% RH] - Relative humidity. Resolution 1%. Range [0-100]. Type: Continuous */ - HUMIDITY = 2; - - /* [hPa] - Hectopascal (1hPa = 100Pa). Resolution 0.1hPa. Range: [1.0-2000.0]. Type: Continuous */ - ATMOSPHERIC_PRESSURE = 3; - - /* [Pa] - Pascal. Resolution 1Pa. Range [-10000-10000]Type: Continuous */ - DIFFERENTIAL_PRESSURE = 4; - - /* Sign indicates state: (+) ALARM, (-) OK. Type: Binary */ - OK_ALARM = 5; - - /* [IAQ] - Iaq index. Resolution 1IAQ. Range [0-500]. Sensor return also calibration status */ - /* as offset to measured value: */ - /* - offset 3000: Sensor not stabilized (always returns 25 IAQ value) */ - /* - offset 2000: Calibration required (sensor returns not accurate values) */ - /* - offset 1000: Calibration on-going (sensor returns not accurate values) */ - /* - offset 0: Calibration done (best accuracy of IAQ sensor) */ - /* Type: Continuous */ - IAQ = 6; - - /* Sign indicates water presence: (+) water not detected, (-) water detected. Type: Binary */ - FLOODING = 7; - - /* [NB] Number of pulses. Resolution 1 pulse. Range [0-16711679]. Type: Continuous */ - PULSE_CNT = 8; - - /* [Wh] - Watthour; Resolution 1Wh. Range [0-16711679]. Number of Watthours in a single period. Type: Continuous */ - ELECTRICITY_METER = 9; - - /* [l] - Liter. Resolution 1l. Range [0-16711679]. Number of litres in a single period. Type: Continuous */ - WATER_METER = 10; - - /* [kPa] - Kilopascal (1kPa = 1000Pa); Resolution 1kPa. Range [-1000-0]. Soil moisture (tension). Type: Continuous */ - SOIL_MOISTURE = 11; - - /* [ppm] - Parts per million. Resolution 1ppm. Range [0-1000000]. Carbon monoxide concentration. Type: Continuous */ - CO_GAS = 12; - - /* [ppm] - Parts per million. Resolution 0.01ppm. Range [0-1000000.00]. Nitrogen dioxide concentration. Type: Continuous*/ - NO2_GAS = 13; - - /* [ppm] - Parts per million. Resolution 1ppm. Range [0-1000000]. Hydrogen sulfide concentration. Type: Continuous */ - H2S_GAS = 14; - - /* [lx] - Illuminance. Resolution 0.1lx. Range [0-100000.0]. Type: Continuous */ - AMBIENT_LIGHT = 15; - - /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3 Range [0-1000]. */ - /* particles with an aerodynamic diameter less than 1 micrometer. Type: Continuous */ - PM_1_0 = 16; // µg/m^3 - - /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3 Range [0-1000]. */ - /* particles with an aerodynamic diameter less than 2.5 micrometers. Type: Continuous */ - PM_2_5 = 17; // µg/m^3 - - /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3 Range [0-1000]. */ - /* particles with an aerodynamic diameter less than 10 micrometers. Type: Continuous */ - PM_10_0 = 18; // µg/m^3 - - /* [dB] - Decibels. Resolution 0.1 dB. Range: [0-130.0]. Noise level. Type: Continuous */ - NOISE_LEVEL = 19; // 0.1 dB - - /* [ppm] - Parts per million. Resolution 1ppm. Range [0-1000000]. Ammonia concentration. Type: Continuous */ - NH3_GAS = 20; - - /* [ppm] - Parts per million. Resolution 1ppm. Range [0-1000000]. Methane concentration. Type: Continuous */ - CH4_GAS = 21; + /* [] - No sensor on the channel */ + MEASUREMENT_TYPE_NO_SENSOR = 0; + + /* [°C] - Celsius degree. Resolution 0.1°C. Range [-273.2:4000.0]. Type: Continuous */ + MEASUREMENT_TYPE_TEMPERATURE = 1; + + /* [% RH] - Relative humidity. Resolution 1%. Range [0:100]. Type: Continuous */ + MEASUREMENT_TYPE_HUMIDITY = 2; + + /* [hPa] - Hectopascal (1hPa = 100Pa). Resolution 0.1hPa. Range: [1.0:2000.0]. Atmospheric pressure. Type: Continuous */ + MEASUREMENT_TYPE_ATMOSPHERIC_PRESSURE = 3; + + /* [Pa] - Pascal. Resolution 1Pa. Range [-10000:10000]. Differential pressure. Type: Continuous */ + MEASUREMENT_TYPE_DIFFERENTIAL_PRESSURE = 4; + + /* Sign indicates state: (+) ALARM, (-) OK. Type: Binary */ + MEASUREMENT_TYPE_OK_ALARM = 5; + + /* [IAQ] - IAQ index. Resolution 1IAQ. Range [0:500]. To get IAQ index the value should be divided by 3. */ + /* Sensor return also calibration status as metadata (is the remainder when the absolute value is divided by 3): */ + /* - 0: Calibration required (sensor returns not accurate values) */ + /* - 1: Calibration on-going (sensor returns not accurate values) */ + /* - 2: Calibration done (best accuracy of IAQ sensor) */ + /* Type: Continuous */ + MEASUREMENT_TYPE_IAQ = 6; + + /* Sign indicates water presence: (+) water not detected, (-) water detected. Type: Binary */ + MEASUREMENT_TYPE_FLOODING = 7; + + /* [NB] Number of pulses. Resolution 1 pulse. Range [0:8000000]. Type: Continuous */ + MEASUREMENT_TYPE_PULSE_CNT = 8; + + /* [Wh] - Watthour; Resolution 1Wh. Range [0:8000000]. Number of Watthours in a single period. Type: Continuous */ + MEASUREMENT_TYPE_ELECTRICITY_METER = 9; + + /* [l] - Liter. Resolution 1l. Range [0:8000000]. Number of litres in a single period. Type: Continuous */ + MEASUREMENT_TYPE_WATER_METER = 10; + + /* [kPa] - Kilopascal (1kPa = 1000Pa); Resolution 1kPa. Range [-1000:0]. Soil moisture (tension). Type: Continuous */ + MEASUREMENT_TYPE_SOIL_MOISTURE = 11; + + /* [ppm] - Parts per million. Resolution 1ppm. Range [0:1000000]. Carbon monoxide concentration. Type: Continuous */ + MEASUREMENT_TYPE_CO_GAS = 12; + + /* [ppm] - Parts per million. Resolution 1.0ppm. Range [0:1000000]. Nitrogen dioxide concentration. Type: Continuous */ + MEASUREMENT_TYPE_NO2_GAS = 13; + + /* [ppm] - Parts per million. Resolution 0.01ppm. Range [0.00:80000.00]. Hydrogen sulfide concentration. Type: Continuous */ + MEASUREMENT_TYPE_H2S_GAS = 14; + + /* [lx] - Lux. Resolution 0.1lx. Range [0.0:100000.0]. Illuminance. Type: Continuous */ + MEASUREMENT_TYPE_AMBIENT_LIGHT = 15; + + /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3. Range [0:1000]. */ + /* Particles with an aerodynamic diameter less than 1 micrometer. Type: Continuous */ + MEASUREMENT_TYPE_PM_1_0 = 16; + + /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3. Range [0:1000]. */ + /* Particles with an aerodynamic diameter less than 2.5 micrometers. Type: Continuous */ + MEASUREMENT_TYPE_PM_2_5 = 17; + + /* [µg/m^3] - Micro gram per cubic meter. Resolution 1µg/m^3. Range [0:1000]. */ + /* Particles with an aerodynamic diameter less than 10 micrometers. Type: Continuous */ + MEASUREMENT_TYPE_PM_10_0 = 18; + + /* [dB] - Decibels. Resolution 0.1 dB. Range: [0.0:200.0]. Noise level. Type: Continuous */ + MEASUREMENT_TYPE_NOISE_LEVEL = 19; + + /* [ppm] - Parts per million. Resolution 1ppm. Range [0:1000000]. Ammonia concentration. Type: Continuous */ + MEASUREMENT_TYPE_NH3_GAS = 20; + + /* [ppm] - Parts per million. Resolution 1ppm. Range [0:1000000]. Methane concentration. Type: Continuous */ + MEASUREMENT_TYPE_CH4_GAS = 21; + + /* [kPa] - Kilopascal (1kPa = 1000Pa, 100kPa = 1bar). Resolution 1kPa. Range [0:200000]. Pressure. Type: Continuous */ + MEASUREMENT_TYPE_HIGH_PRESSURE = 22; + + /* [mm] - Millimeter. Resolution 1mm. Range [0:100000]. Distance. Type: Continuous */ + MEASUREMENT_TYPE_DISTANCE_MM = 23; + + /* [l] - Liter. Resolution 1l. Range [0:1000000]. Accumulative water meter (minor). Type: Continuous */ + MEASUREMENT_TYPE_WATER_METER_ACC_MINOR = 24; + + /* [hl] - Hectoliter. Resolution 1hl. Range [0:1000000]. Accumulative water meter (major). Type: Continuous */ + MEASUREMENT_TYPE_WATER_METER_ACC_MAJOR = 25; + + /* [ppm] - Parts per million. Resolution 1ppm. Range [0:1000000]. Carbon dioxide concentration. Type: Continuous */ + MEASUREMENT_TYPE_CO2_GAS = 26; + + /* [% RH] - Relative humidity. Resolution 0.1%. Range [0.0:100.0]. Type: Continuous */ + MEASUREMENT_TYPE_HUMIDITY_ACCURATE = 27; + + /* [sIAQ] - Static IAQ index. Resolution 1IAQ. Range [0:10000]. To get static IAQ index the value should be divided by 3. */ + /* Sensor return also calibration status as metadata (is the remainder when the absolute value is divided by 3): */ + /* - 0: Calibration required (sensor returns not accurate values) */ + /* - 1: Calibration on-going (sensor returns not accurate values) */ + /* - 2: Calibration done (best accuracy of IAQ sensor) */ + /* Type: Continuous */ + MEASUREMENT_TYPE_STATIC_IAQ = 28; + + /* [ppm] - Parts per million. Resolution 1ppm. Range [0:1000000]. CO2 equivalent. */ + /* To get CO2 equivalent the value should be divided by 3. */ + /* Sensor return also calibration status as metadata (is the remainder when the absolute value is divided by 3): */ + /* - 0: Calibration required (sensor returns not accurate values) */ + /* - 1: Calibration on-going (sensor returns not accurate values) */ + /* - 2: Calibration done (best accuracy of IAQ sensor) */ + /* Type: Continuous */ + MEASUREMENT_TYPE_CO2_EQUIVALENT = 29; + + /* [ppm] - Parts per million. Resolution 1ppm. Range [0:100000]. Breath VOC estimate. */ + /* To get breath VOC estimate the value should be divided by 3. */ + /* Sensor return also calibration status as metadata (is the remainder when the absolute value is divided by 3): */ + /* - 0: Calibration required (sensor returns not accurate values) */ + /* - 1: Calibration on-going (sensor returns not accurate values) */ + /* - 2: Calibration done (best accuracy of IAQ sensor) */ + /* Type: Continuous */ + MEASUREMENT_TYPE_BREATH_VOC = 30; + + /* Special measurement type reserved for cellular gateway. */ + /* Type: Continuous */ + MEASUREMENT_TYPE_CELLULAR_GATEWAY = 31; + + /* [%] - Percentage. Resolution 0.01%. Range [0.00:100.00]. Type: Continuous */ + MEASUREMENT_TYPE_PERCENTAGE = 32; + + /* [mV] - Milivolt. Resolution 0.1mV. Range [0.0:100000.0]. Type: Continuous */ + MEASUREMENT_TYPE_VOLTAGE = 33; + + /* [mA] - Milliampere. Resolution 0.01mA. Range [0.0:10000.00]. Type: Continuous */ + MEASUREMENT_TYPE_CURRENT = 34; + + /* [NB] Number of pulses. Resolution 1 pulse. Range [0:1000000]. Type: Continuous */ + MEASUREMENT_TYPE_PULSE_CNT_ACC_MINOR = 35; + + /* [kNB] Number of kilopulses. Resolution 1 kilopulse. Range [0:1000000]. Type: Continuous */ + MEASUREMENT_TYPE_PULSE_CNT_ACC_MAJOR = 36; + + /* [Wh] - Watt-hour; Resolution 1Wh. Range [0:1000000]. Number of watt-hours in a single period. Type: Continuous */ + MEASUREMENT_TYPE_ELEC_METER_ACC_MINOR = 37; + + /* [kWh] - Kilowatt-hour; Resolution 1kWh. Range [0:1000000]. Number of kilowatt-hours in a single period. Type: Continuous */ + MEASUREMENT_TYPE_ELEC_METER_ACC_MAJOR = 38; + + /* [NB] Number of pulses (wide range). Resolution 1 pulse. Range [0:999999]. Type: Continuous */ + MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MINOR = 39; + + /* [MNB] Number of megapulses (wide range). Resolution 1 megapulse. Range [0:999999]. Type: Continuous */ + MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MAJOR = 40; + + /* [mA] - Milliampere. Resolution 0.001mA. Range [-4 000.000:4 000.000]. Type: Continuous */ + MEASUREMENT_TYPE_CURRENT_PRECISE = 41; + + /* Sign indicates state: (+) ON, (-) OFF. Type: Binary */ + MEASUREMENT_TYPE_OUTPUT_CONTROL = 42; } diff --git a/common/transport/coap/src/main/proto/efento/proto_measurements.proto b/common/transport/coap/src/main/proto/efento/proto_measurements.proto index f8549feb54..80af07d958 100644 --- a/common/transport/coap/src/main/proto/efento/proto_measurements.proto +++ b/common/transport/coap/src/main/proto/efento/proto_measurements.proto @@ -19,103 +19,108 @@ import "efento/proto_measurement_types.proto"; option java_package = "org.thingsboard.server.gen.transport.coap"; option java_outer_classname = "MeasurementsProtos"; -message ProtoChannel{ - /* Type of channel */ +message ProtoChannel { + + /* Type of channel */ MeasurementType type = 1; - /* Timestamp of the first sample (the oldest one) in seconds since UNIX EPOCH 01-01-1970 */ + /* Timestamp of the first sample (the oldest one) in seconds since UNIX EPOCH 01-01-1970 */ int32 timestamp = 2; - /* Only used for 'Continuous' sensor types. Value used as the starting point for calculating the values of all */ - /* measurements in the package. */ - /* Format defined by 'MeasurementType' field */ + /* Only used for 'Continuous' sensor types. Value used as the starting point for calculating the values of all */ + /* measurements in the package. */ + /* Format defined by 'MeasurementType' field */ sint32 start_point = 4; - /* 'Continuous' sensor types */ - /* Value of the offset from the 'start_point' for each measurement in the package. The oldest sample first ([0]). */ - /* 'sample_offsets' format defined by 'MeasurementType' field. */ - /* Example: MeasurementType = 1 (temperature), start_point = 100, sample_offsets[0] = 15, sample_offsets[1] = 20 */ - /* 1st sample in the package temperature value = 11.5 °C, 2nd sample in the package temperature value = 12 °C */ - /* Calculating timestamps of the measurements: timestamp = 1606391700, measurement_period_base = 60, */ - /* measurement_period_factor = 1. Timestamp of the 1st sample = 1606391700, timestamp of the 2nd sample = 1606391760 */ - /* 'Binary' sensor types: */ - /* Absolute value of the 'sample_offsets' field indicates the offset in seconds from 'timestamp' field. */ - /* Sign (- or +) indicates the state of measurements depend of sensor type. */ - /* Value of this field equals to '1' or '-1' indicates the state at the 'timestamp'. Other values */ - /* indicate the state of the relay at the time (in seconds) equal to 'timestamp' + value. */ - /* Values of this field are incremented starting from 1 (1->0: state at the time */ - /* of 'timestamp', 2->1: state at the time equal to 'timestamp' + 1 s, 3->2 : */ - /* state at the time equal to 'timestamp' + 2 s, etc.). The first and the last sample define the time range of the */ - /* measurements. Only state changes in the time range are included in the 'sample_offsets' field */ - /* Examples: if 'timestamp' value is 1553518060 and 'sample_offsets' equals '1', it means that at 1553518060 the state */ - /* was high, if 'timestamp' value is 1553518060 and 'sample_offsets' equals '-9', it means at 1553518068 the state was low */ + /* 'Continuous' sensor types */ + /* Value of the offset from the 'start_point' for each measurement in the package. The oldest sample first ([0]). */ + /* 'sample_offsets' format defined by 'MeasurementType' field. */ + /* If the 'sample_offset' has a value from the range [8355840: 8388607], it should be interpreted as a sensor error code. */ + /* In that case value of the 'start_point' field should not be added to this 'sample_offset'. See ES6-264 for error codes. */ + /* Example: MeasurementType = 1 (temperature), start_point = 100, sample_offsets[0] = 15, sample_offsets[1] = 20, */ + /* sample_offset[2] = 8388605 */ + /* 1st sample in the package temperature value = 11.5 °C, 2nd sample in the package temperature value = 12 °C */ + /* 3rd sample in the package has no temperature value. It has information about failure of MCP9808 (temperature) sensor. */ + /* Calculating timestamps of the measurements: timestamp = 1606391700, measurement_period_base = 60, */ + /* measurement_period_factor = 1. Timestamp of the 1st sample = 1606391700, timestamp of the 2nd sample = 1606391760, */ + /* timestamp of the 3rd sample 1606391820 */ + + /* 'Binary' sensor types: */ + /* Absolute value of the 'sample_offsets' field indicates the offset in seconds from 'timestamp' field. */ + /* Sign (- or +) indicates the state of measurements depending on the sensor type. */ + /* Value of this field equals to '1' or '-1' indicates the state at the 'timestamp'. Other values */ + /* indicate the state of the relay at the time (in seconds) equal to 'timestamp' + absolute value -1. */ + /* Values of this field are incremented starting from 1 (1->0: state at the time */ + /* of 'timestamp', 2->1: state at the time equal to 'timestamp' + 1 s, 3->2 : */ + /* state at the time equal to 'timestamp' + 2 s, etc.). The first and the last sample define the time range of the */ + /* measurements. Only state changes in the time range are included in the 'sample_offsets' field */ + /* Examples: if 'timestamp' value is 1553518060 and 'sample_offsets' equals '1', it means that at 1553518060 the state */ + /* was high, if 'timestamp' value is 1553518060 and 'sample_offsets' equals '-9', it means at 1553518068 the state was low */ repeated sint32 sample_offsets = 5 [packed=true]; - /* Deprecated - configuration is sent to endpoint 'c' */ - //int32 lo_threshold = 6; + /* Deprecated - configuration is sent to endpoint 'c' */ + /* int32 lo_threshold = 6; */ + reserved 6; - /* Deprecated - configuration is sent to endpoint 'c' */ - //int32 hi_threshold = 7; + /* Deprecated - configuration is sent to endpoint 'c' */ + /* int32 hi_threshold = 7; */ + reserved 7; - /* Deprecated - configurationis sent to endpoint 'c' */ - //int32 diff_threshold = 8; - } + /* Deprecated - configurations sent to endpoint 'c' */ + /* int32 diff_threshold = 8; */ + reserved 8; +} message ProtoMeasurements { - /* serial number of the device */ + /* Serial number of the device */ bytes serial_num = 1; - /* true - battery ok, false - battery low */ + /* Battery status: true - battery ok, false - battery low */ bool battery_status = 2; - /* 'Measurement_period_base' and 'measurement_period_factor' define how often the measurements are taken. */ - /* Sensors of 'Continuous' type take measurement each Measurement_period_base * measurement_period_factor. */ - /* Sensors of 'Binary' type take measurement each Measurement_period_base. */ - /* For backward compatibility with versions 5.x in case of binary/mixed sensors, if the 'measurement_period_factor' is */ - /* not sent (equal to 0), then the default value '14' shall be used for period calculation. */ - /* For backward compatibility with versions 5.x in case of continues sensors, if the measurement_period_factor is */ - /* not sent (equal to 0), then the default value '1' shall be used for period calculation. */ - /* measurement period base in seconds */ + /* 'Measurement_period_base' and 'measurement_period_factor' define how often the measurements are taken. */ + /* Sensors of 'Continuous' type take measurement each Measurement_period_base * measurement_period_factor. */ + /* Sensors of 'Binary' type take measurement each Measurement_period_base. */ + /* For backward compatibility with versions 5.x in case of binary/mixed sensors, if the 'measurement_period_factor' is */ + /* not sent (equal to 0), then the default value '14' shall be used for period calculation. */ + /* For backward compatibility with versions 5.x in case of continues sensors, if the measurement_period_factor is */ + /* not sent (equal to 0), then the default value '1' shall be used for period calculation. */ + /* measurement period base in seconds */ uint32 measurement_period_base = 3; - /* Measurement period factor */ + /* Measurement period factor */ uint32 measurement_period_factor = 8; repeated ProtoChannel channels = 4; - /* Timestamp of the next scheduled transmission. If the device will not send data until this time, */ - /* it should be considered as 'lost' */ + /* Timestamp of the next scheduled transmission. If the device will not send data until this time, */ + /* it should be considered as 'lost' */ uint32 next_transmission_at = 5; - /* reason of transmission - unsigned integer where each bit indicates different */ - /* possible communication reason. Can be more than one */ - /* - bit 0: first message after sensor reset */ - /* - bit 1: user button triggered */ - /* - bit 2: user BLE triggered */ - /* - bit 3-7: number of retries -> incremented after each unsuccessful transmission. Max value 4. */ - /* Set to 0 after a successful transmission. */ - /* - bit 8: channel 1 lower threshold exceeded */ - /* - bit 9: channel 1 lower threshold returned */ - /* - bit 10: channel 1 higher threshold exceeded */ - /* - bit 11: channel 1 higher threshold returned */ - /* - bit 12: channel 1 differential threshold crossed */ - /* - bits 13-17: channel 2 thresholds (same as for channel 1) */ - /* - bits 18-22: channel 3 thresholds (same as for channel 1) */ - /* - bits 23-27: channel 4 or 5 or 6 thresholds (same as for channel 1) */ + /* Reason of transmission - unsigned integer where each bit indicates different possible communication reason. */ + /* Can be more than one: */ + /* - bit 0: first message after sensor reset */ + /* - bit 1: user button triggered */ + /* - bit 2: user BLE triggered */ + /* - bit 3-7: number of retries -> incremented after each unsuccessful transmission. Max value 31. */ + /* Set to 0 after a successful transmission. */ + /* - bit 8...19: rule 1...12 was met */ + /* - bit 20: triggered after the end of the limit */ uint32 transfer_reason = 6; - /* Signal strength level mapped from RSSI */ - /* - 0 : 113 dBm or less */ - /* - 1 : 111 dBm */ - /* - 2...30 : 109...-53 dBm */ - /* - 31 : -51 dBm or greater */ - /* - 99 : Not known or not detectable */ + /* Signal strength level mapped from RSSI: */ + /* - 0: RSSI < -110 dBm */ + /* - 1: -110 dBm <= RSSI < -109 dBm */ + /* - 2...61: -109 <= RSSI < -108 dBm ... -50 dBm <= RSSI < -49 dBm */ + /* - 62: -49 dBm <= RSSI < -48 dBm */ + /* - 63: RSSI >= -48 dBm */ + /* - 99: Not known or not detectable */ uint32 signal = 7; - /* Hash of the current configuration. Hash value changes each time a device receives a new configuration */ + /* Hash of the current configuration. Hash value changes each time a device receives a new configuration */ uint32 hash = 9; - /* Optional string up to 36 bytes long. Can be set to any user define value or hold device's IMEI */ + /* Optional string up to 36 bytes long. Can be set to any user define value or hold device's IMEI */ string cloud_token = 16; } \ No newline at end of file diff --git a/common/transport/coap/src/main/proto/efento/proto_rule.proto b/common/transport/coap/src/main/proto/efento/proto_rule.proto index 4079683a3f..12550426b1 100644 --- a/common/transport/coap/src/main/proto/efento/proto_rule.proto +++ b/common/transport/coap/src/main/proto/efento/proto_rule.proto @@ -50,11 +50,19 @@ option java_outer_classname = "ProtoRuleProtos"; /* - CO2_EQUIVALENT - [ppm] - Parts per million. Resolution 1ppm. Range [0:1000000]. Carbon dioxide equivalent. */ /* - BREATH_VOC - [ppm] - Parts per million. Resolution 1ppm. Range [0:100000]. Breath VOC estimate. */ /* - PERCENTAGE - [%] - Percentage. Resolution 0.01%. Range [0.00:100.00]. */ +/* - VOLTAGE - [mV] - Milivolt. Resolution 0.1mV. Range [0.0:100000.0]. */ +/* - CURRENT - [mA] - Miliampere. Resolution 0.01mA. Range [0.00:10000.00]. */ /* - PULSE_CNT_ACC_MINOR - [NB] - Number of pulses. Resolution 1 pulse. Range [0:1000000]. Accumulative pulse counter (minor). */ /* - PULSE_CNT_ACC_MAJOR - [kNB] - Number of kilopulses. Resolution 1 kilopulse. Range [0:1000000]. */ /* Accumulative pulse counter (major). */ /* - ELEC_METER_ACC_MINOR - [Wh] - Watt-hour. Resolution 1Wh. Range [0:1000000]. Accumulative electricity meter (minor). */ /* - ELEC_METER_ACC_MAJOR - [kWh] - Kilowatt-hour. Resolution 1kWh. Range [0:1000000]. Accumulative electricity meter (major). */ +/* - PULSE_CNT_ACC_WIDE_MINOR - [NB] - Number of pulses. Resolution 1 pulse. Range [0:999999]. */ +/* Accumulative pulse counter wide range (minor). */ +/* - PULSE_CNT_ACC_WIDE_MAJOR - [MNB] - Number of megapulses. Resolution 1 megapulse. Range [0:999999]. */ +/* Accumulative pulse counter wide range (major). */ +/* - CURRENT_PRECISE - [mA] - Miliampere. Resolution 0.001mA. Range [-4 000.000:4 000.000]. */ +/* - OUTPUT_CONTROL - Not applicable */ /* Encoding R: used to set relative values in the Rules (e.g. differential threshold and hysteresis) */ /* - TEMPERATURE - [°C] - Celsius degree. Resolution 0.1°C. Range [0.1:4273.2]. */ @@ -88,11 +96,19 @@ option java_outer_classname = "ProtoRuleProtos"; /* - CO2_EQUIVALENT - [ppm] - Parts per million. Resolution 1ppm. Range [1:1000000]. Carbon dioxide equivalent. */ /* - BREATH_VOC - [ppm] - Parts per million. Resolution 1ppm. Range [1:100000]. Breath VOC estimate. */ /* - PERCENTAGE - [%] - Percentage. Resolution 0.01%. Range [0.01:100.00]. */ +/* - VOLTAGE - [mV] - Milivolt. Resolution 0.1mV. Range [0.1:100000.0]. */ +/* - CURRENT - [mA] - Miliampere. Resolution 0.01mA. Range [0.01:10000.00]. */ /* - PULSE_CNT_ACC_MINOR - [NB] - Number of pulses. Resolution 1 pulse. Range [1:1000000]. Accumulative pulse counter (minor). */ /* - PULSE_CNT_ACC_MAJOR - [kNB] - Number of kilopulses. Resolution 1 kilopulse. Range [1:1000000]. */ /* Accumulative pulse counter (major). */ /* - ELEC_METER_ACC_MINOR - [Wh] - Watt-hour. Resolution 1Wh. Range [1:1000000]. Accumulative electricity meter (minor). */ /* - ELEC_METER_ACC_MAJOR - [kWh] - Kilowatt-hour. Resolution 1kWh. Range [1:1000000]. Accumulative electricity meter (major). */ +/* - PULSE_CNT_ACC_WIDE_MINOR - [NB] - Number of pulses. Resolution 1 pulse. Range [1:999999]. */ +/* Accumulative pulse counter wide range (minor). */ +/* - PULSE_CNT_ACC_WIDE_MAJOR - [MNB] - Number of megapulses. Resolution 1 megapulse. Range [1:999999]. */ +/* Accumulative pulse counter wide range (major). */ +/* - CURRENT_PRECISE - [mA] - Miliampere. Resolution 0.001mA. Range [0.001:8 000.000]. */ +/* - OUTPUT_CONTROL - Not applicable */ /* Condition to be checked by the device. If the condition is true, an action is triggered */ enum Condition { @@ -202,6 +218,10 @@ enum Action { /* To trigger the transmission with ACK */ ACTION_TRIGGER_TRANSMISSION_WITH_ACK = 3; + + /* To change BLE advertising period mode to fast (with lower user-configured advertising interval). */ + /* Once the rule is deactived avertising period mode returns to previously configured value. */ + ACTION_FAST_ADVERTISING_MODE = 4; } /* Type of a rule calendars. */ diff --git a/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/efento/CoapEfentTransportResourceTest.java b/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/efento/CoapEfentTransportResourceTest.java new file mode 100644 index 0000000000..1b6327d62d --- /dev/null +++ b/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/efento/CoapEfentTransportResourceTest.java @@ -0,0 +1,321 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.efento; + +import com.google.protobuf.ByteString; +import org.junit.jupiter.api.BeforeAll; +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.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType; +import org.thingsboard.server.gen.transport.coap.MeasurementsProtos; +import org.thingsboard.server.gen.transport.coap.MeasurementsProtos.ProtoMeasurements; +import org.thingsboard.server.transport.coap.CoapTransportContext; +import org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils; + +import java.nio.ByteBuffer; +import java.time.Instant; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +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.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_AMBIENT_LIGHT; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_ATMOSPHERIC_PRESSURE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_BREATH_VOC; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_CO2_EQUIVALENT; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_CURRENT; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_CURRENT_PRECISE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_DIFFERENTIAL_PRESSURE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_DISTANCE_MM; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_ELECTRICITY_METER; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_ELEC_METER_ACC_MAJOR; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_ELEC_METER_ACC_MINOR; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_FLOODING; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_HIGH_PRESSURE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_HUMIDITY; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_HUMIDITY_ACCURATE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_IAQ; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_OK_ALARM; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_OUTPUT_CONTROL; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_PERCENTAGE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_PULSE_CNT; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_PULSE_CNT_ACC_MAJOR; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_PULSE_CNT_ACC_MINOR; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MAJOR; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MINOR; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_SOIL_MOISTURE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_STATIC_IAQ; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_VOLTAGE; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_WATER_METER; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_WATER_METER_ACC_MAJOR; +import static org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos.MeasurementType.MEASUREMENT_TYPE_WATER_METER_ACC_MINOR; +import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.convertTimestampToUtcString; + +class CoapEfentTransportResourceTest { + + private static CoapEfentoTransportResource coapEfentoTransportResource; + + @BeforeAll + static void setUp() { + var ctxMock = mock(CoapTransportContext.class); + coapEfentoTransportResource = new CoapEfentoTransportResource(ctxMock, "testName"); + } + + @Test + void checkContinuousSensorWithSomeMeasurements() { + long tsInSec = Instant.now().getEpochSecond(); + ProtoMeasurements measurements = ProtoMeasurements.newBuilder() + .setSerialNum(integerToByteString(1234)) + .setCloudToken("test_token") + .setMeasurementPeriodBase(180) + .setMeasurementPeriodFactor(5) + .setBatteryStatus(true) + .setSignal(0) + .setNextTransmissionAt(1000) + .setTransferReason(0) + .setHash(0) + .addAllChannels(List.of(MeasurementsProtos.ProtoChannel.newBuilder() + .setType(MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) + .setTimestamp(Math.toIntExact(tsInSec)) + .addAllSampleOffsets(List.of(223, 224)) + .build(), + MeasurementsProtos.ProtoChannel.newBuilder() + .setType(MeasurementType.MEASUREMENT_TYPE_HUMIDITY) + .setTimestamp(Math.toIntExact(tsInSec)) + .addAllSampleOffsets(List.of(20, 30)) + .build() + )) + .build(); + List efentoMeasurements = coapEfentoTransportResource.getEfentoMeasurements(measurements, UUID.randomUUID()); + assertThat(efentoMeasurements).hasSize(2); + assertThat(efentoMeasurements.get(0).getTs()).isEqualTo(tsInSec * 1000); + assertThat(efentoMeasurements.get(0).getValues().getAsJsonObject().get("temperature_1").getAsDouble()).isEqualTo(22.3); + assertThat(efentoMeasurements.get(0).getValues().getAsJsonObject().get("humidity_2").getAsDouble()).isEqualTo(20); + assertThat(efentoMeasurements.get(1).getTs()).isEqualTo((tsInSec + 180 * 5) * 1000); + assertThat(efentoMeasurements.get(1).getValues().getAsJsonObject().get("temperature_1").getAsDouble()).isEqualTo(22.4); + assertThat(efentoMeasurements.get(1).getValues().getAsJsonObject().get("humidity_2").getAsDouble()).isEqualTo(30); + checkDefaultMeasurements(measurements, efentoMeasurements, 180 * 5, false); + } + + @ParameterizedTest + @MethodSource + void checkContinuousSensor(MeasurementType measurementType, List sampleOffsets, String property, double expectedValue) { + long tsInSec = Instant.now().getEpochSecond(); + ProtoMeasurements measurements = ProtoMeasurements.newBuilder() + .setSerialNum(integerToByteString(1234)) + .setCloudToken("test_token") + .setMeasurementPeriodBase(180) + .setMeasurementPeriodFactor(0) + .setBatteryStatus(true) + .setSignal(0) + .setNextTransmissionAt(1000) + .setTransferReason(0) + .setHash(0) + .addAllChannels(List.of(MeasurementsProtos.ProtoChannel.newBuilder() + .setType(measurementType) + .setTimestamp(Math.toIntExact(tsInSec)) + .addAllSampleOffsets(sampleOffsets) + .build() + )) + .build(); + List efentoMeasurements = coapEfentoTransportResource.getEfentoMeasurements(measurements, UUID.randomUUID()); + assertThat(efentoMeasurements).hasSize(1); + assertThat(efentoMeasurements.get(0).getTs()).isEqualTo(tsInSec * 1000); + assertThat(efentoMeasurements.get(0).getValues().getAsJsonObject().get(property).getAsDouble()).isEqualTo(expectedValue); + checkDefaultMeasurements(measurements, efentoMeasurements, 180, false); + } + + private static Stream checkContinuousSensor() { + return Stream.of( + Arguments.of(MEASUREMENT_TYPE_TEMPERATURE, List.of(223), "temperature_1", 22.3), + Arguments.of(MEASUREMENT_TYPE_WATER_METER, List.of(1050), "pulse_counter_water_1", 1050), + Arguments.of(MEASUREMENT_TYPE_HUMIDITY, List.of(20), "humidity_1", 20), + Arguments.of(MEASUREMENT_TYPE_ATMOSPHERIC_PRESSURE, List.of(1013), "pressure_1", 101.3), + Arguments.of(MEASUREMENT_TYPE_DIFFERENTIAL_PRESSURE, List.of(500), "pressure_diff_1", 500), + Arguments.of(MEASUREMENT_TYPE_PULSE_CNT, List.of(300), "pulse_cnt_1", 300), + Arguments.of(MEASUREMENT_TYPE_IAQ, List.of(150), "iaq_1", 150), + Arguments.of(MEASUREMENT_TYPE_ELECTRICITY_METER, List.of(1200), "watt_hour_1", 1200), + Arguments.of(MEASUREMENT_TYPE_SOIL_MOISTURE, List.of(35), "soil_moisture_1", 35), + Arguments.of(MEASUREMENT_TYPE_AMBIENT_LIGHT, List.of(500), "ambient_light_1", 50), + Arguments.of(MEASUREMENT_TYPE_HIGH_PRESSURE, List.of(200000), "high_pressure_1", 200000), + Arguments.of(MEASUREMENT_TYPE_DISTANCE_MM, List.of(1500), "distance_mm_1", 1500), + Arguments.of(MEASUREMENT_TYPE_WATER_METER_ACC_MINOR, List.of(125), "acc_counter_water_minor_1", 125), + Arguments.of(MEASUREMENT_TYPE_WATER_METER_ACC_MAJOR, List.of(2500), "acc_counter_water_major_1", 2500), + Arguments.of(MEASUREMENT_TYPE_HUMIDITY_ACCURATE, List.of(525), "humidity_relative_1", 52.5), + Arguments.of(MEASUREMENT_TYPE_STATIC_IAQ, List.of(110), "static_iaq_1", 110), + Arguments.of(MEASUREMENT_TYPE_CO2_EQUIVALENT, List.of(450), "co2_ppm_1", 450), + Arguments.of(MEASUREMENT_TYPE_BREATH_VOC, List.of(220), "breath_voc_ppm_1", 220), + Arguments.of(MEASUREMENT_TYPE_PERCENTAGE, List.of(80), "percentage_1", 0.80), + Arguments.of(MEASUREMENT_TYPE_VOLTAGE, List.of(2400), "voltage_1", 240), + Arguments.of(MEASUREMENT_TYPE_CURRENT, List.of(550), "current_1", 5.5), + Arguments.of(MEASUREMENT_TYPE_PULSE_CNT_ACC_MINOR, List.of(180), "pulse_cnt_minor_1", 180), + Arguments.of(MEASUREMENT_TYPE_PULSE_CNT_ACC_MAJOR, List.of(1200), "pulse_cnt_major_1", 1200), + Arguments.of(MEASUREMENT_TYPE_ELEC_METER_ACC_MINOR, List.of(550), "elec_meter_minor_1", 550), + Arguments.of(MEASUREMENT_TYPE_ELEC_METER_ACC_MAJOR, List.of(5500), "elec_meter_major_1", 5500), + Arguments.of(MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MINOR, List.of(230), "pulse_cnt_wide_minor_1", 230), + Arguments.of(MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MAJOR, List.of(1700), "pulse_cnt_wide_major_1", 1700), + Arguments.of(MEASUREMENT_TYPE_CURRENT_PRECISE, List.of(275), "current_precise_1", 0.275) + ); + } + + @Test + void checkBinarySensor() { + long tsInSec = Instant.now().getEpochSecond(); + ProtoMeasurements measurements = ProtoMeasurements.newBuilder() + .setSerialNum(integerToByteString(1234)) + .setCloudToken("test_token") + .setMeasurementPeriodBase(180) + .setMeasurementPeriodFactor(0) + .setBatteryStatus(true) + .setSignal(0) + .setNextTransmissionAt(1000) + .setTransferReason(0) + .setHash(0) + .addChannels(MeasurementsProtos.ProtoChannel.newBuilder() + .setType(MEASUREMENT_TYPE_OK_ALARM) + .setTimestamp(Math.toIntExact(tsInSec)) + .addAllSampleOffsets(List.of(1, 1)) + .build()) + .build(); + List efentoMeasurements = coapEfentoTransportResource.getEfentoMeasurements(measurements, UUID.randomUUID()); + assertThat(efentoMeasurements).hasSize(1); + assertThat(efentoMeasurements.get(0).getTs()).isEqualTo(tsInSec * 1000); + assertThat(efentoMeasurements.get(0).getValues().getAsJsonObject().get("ok_alarm_1").getAsString()).isEqualTo("ALARM"); + checkDefaultMeasurements(measurements, efentoMeasurements, 180 * 14, true); + } + + @ParameterizedTest + @MethodSource + void checkBinarySensorWhenValueIsVarying(MeasurementType measurementType, String property, String expectedValueWhenOffsetNotOk, String expectedValueWhenOffsetOk) { + long tsInSec = Instant.now().getEpochSecond(); + ProtoMeasurements measurements = ProtoMeasurements.newBuilder() + .setSerialNum(integerToByteString(1234)) + .setCloudToken("test_token") + .setMeasurementPeriodBase(180) + .setMeasurementPeriodFactor(1) + .setBatteryStatus(true) + .setSignal(0) + .setNextTransmissionAt(1000) + .setTransferReason(0) + .setHash(0) + .addChannels(MeasurementsProtos.ProtoChannel.newBuilder() + .setType(measurementType) + .setTimestamp(Math.toIntExact(tsInSec)) + .addAllSampleOffsets(List.of(1, -10)) + .build()) + .build(); + List efentoMeasurements = coapEfentoTransportResource.getEfentoMeasurements(measurements, UUID.randomUUID()); + assertThat(efentoMeasurements).hasSize(2); + assertThat(efentoMeasurements.get(0).getTs()).isEqualTo(tsInSec * 1000); + assertThat(efentoMeasurements.get(0).getValues().getAsJsonObject().get(property).getAsString()).isEqualTo(expectedValueWhenOffsetNotOk); + assertThat(efentoMeasurements.get(1).getTs()).isEqualTo((tsInSec + 9) * 1000); + assertThat(efentoMeasurements.get(1).getValues().getAsJsonObject().get(property).getAsString()).isEqualTo(expectedValueWhenOffsetOk); + checkDefaultMeasurements(measurements, efentoMeasurements, 180, true); + } + + private static Stream checkBinarySensorWhenValueIsVarying() { + return Stream.of( + Arguments.of(MEASUREMENT_TYPE_OK_ALARM, "ok_alarm_1", "ALARM", "OK"), + Arguments.of(MEASUREMENT_TYPE_FLOODING, "flooding_1", "WATER_DETECTED", "OK"), + Arguments.of(MEASUREMENT_TYPE_OUTPUT_CONTROL, "output_control_1", "ON", "OFF") + ); + } + + @Test + void checkExceptionWhenChannelsListIsEmpty() { + ProtoMeasurements measurements = ProtoMeasurements.newBuilder() + .setSerialNum(integerToByteString(1234)) + .setCloudToken("test_token") + .setMeasurementPeriodBase(180) + .setMeasurementPeriodFactor(1) + .setBatteryStatus(true) + .setSignal(0) + .setNextTransmissionAt(1000) + .setTransferReason(0) + .setHash(0) + .build(); + UUID sessionId = UUID.randomUUID(); + + assertThatThrownBy(() -> coapEfentoTransportResource.getEfentoMeasurements(measurements, sessionId)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[" + sessionId + "]: Failed to get Efento measurements, reason: channels list is empty!"); + } + + @Test + void checkExceptionWhenValuesMapIsEmpty() { + long tsInSec = Instant.now().getEpochSecond(); + ProtoMeasurements measurements = ProtoMeasurements.newBuilder() + .setSerialNum(integerToByteString(1234)) + .setCloudToken("test_token") + .setMeasurementPeriodBase(180) + .setMeasurementPeriodFactor(1) + .setBatteryStatus(true) + .setSignal(0) + .setNextTransmissionAt(1000) + .setTransferReason(0) + .setHash(0) + .addChannels(MeasurementsProtos.ProtoChannel.newBuilder() + .setType(MEASUREMENT_TYPE_TEMPERATURE) + .setTimestamp(Math.toIntExact(tsInSec)) + .build()) + .build(); + UUID sessionId = UUID.randomUUID(); + + assertThatThrownBy(() -> coapEfentoTransportResource.getEfentoMeasurements(measurements, sessionId)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[" + sessionId + "]: Failed to collect Efento measurements, reason, values map is empty!"); + } + + public static ByteString integerToByteString(Integer intValue) { + // Allocate a ByteBuffer with the size of an integer (4 bytes) + ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES); + + // Put the integer value into the ByteBuffer + buffer.putInt(intValue); + + // Convert the ByteBuffer to a byte array + byte[] byteArray = buffer.array(); + + // Create a ByteString from the byte array + return ByteString.copyFrom(byteArray); + } + + private void checkDefaultMeasurements(ProtoMeasurements incomingMeasurements, + List actualEfentoMeasurements, + long expectedMeasurementInterval, + boolean isBinarySensor) { + for (int i = 0; i < actualEfentoMeasurements.size(); i++) { + CoapEfentoTransportResource.EfentoTelemetry actualEfentoMeasurement = actualEfentoMeasurements.get(i); + assertThat(actualEfentoMeasurement.getValues().getAsJsonObject().get("serial").getAsString()).isEqualTo(CoapEfentoUtils.convertByteArrayToString(incomingMeasurements.getSerialNum().toByteArray())); + assertThat(actualEfentoMeasurement.getValues().getAsJsonObject().get("battery").getAsString()).isEqualTo(incomingMeasurements.getBatteryStatus() ? "ok" : "low"); + MeasurementsProtos.ProtoChannel protoChannel = incomingMeasurements.getChannelsList().get(0); + long measuredAt = isBinarySensor ? + TimeUnit.SECONDS.toMillis(protoChannel.getTimestamp()) + Math.abs(TimeUnit.SECONDS.toMillis(protoChannel.getSampleOffsetsList().get(i))) - 1000 : + TimeUnit.SECONDS.toMillis(protoChannel.getTimestamp() + i * expectedMeasurementInterval); + assertThat(actualEfentoMeasurement.getValues().getAsJsonObject().get("measured_at").getAsString()).isEqualTo(convertTimestampToUtcString(measuredAt)); + assertThat(actualEfentoMeasurement.getValues().getAsJsonObject().get("next_transmission_at").getAsString()).isEqualTo(convertTimestampToUtcString(TimeUnit.SECONDS.toMillis(incomingMeasurements.getNextTransmissionAt()))); + assertThat(actualEfentoMeasurement.getValues().getAsJsonObject().get("signal").getAsLong()).isEqualTo(incomingMeasurements.getSignal()); + assertThat(actualEfentoMeasurement.getValues().getAsJsonObject().get("measurement_interval").getAsDouble()).isEqualTo(expectedMeasurementInterval); + } + } + +} 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 4825c8922b..7e5711e1de 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 @@ -202,8 +202,8 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @Operation(summary = "Post time-series data (postTelemetry)", - description = "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) 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 9c86b23084..d31d47fcd4 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 @@ -82,7 +82,7 @@ public class TbLwM2MDtlsBootstrapCertificateVerifier implements NewAdvancedCerti staticCertificateVerifier = new StaticNewAdvancedCertificateVerifier(trustedCertificates, new RawPublicKeyIdentity[0], null); } } catch (Exception e) { - log.warn("ailed to initialize the LwM2M certificate verifier", e); + log.warn("Failed to initialize the LwM2M certificate verifier", e); } } diff --git a/common/util/src/main/java/org/thingsboard/common/util/DeduplicationUtil.java b/common/util/src/main/java/org/thingsboard/common/util/DeduplicationUtil.java new file mode 100644 index 0000000000..fd25e8b924 --- /dev/null +++ b/common/util/src/main/java/org/thingsboard/common/util/DeduplicationUtil.java @@ -0,0 +1,44 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.common.util; + +import org.springframework.util.ConcurrentReferenceHashMap; + +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.springframework.util.ConcurrentReferenceHashMap.ReferenceType.SOFT; + +public class DeduplicationUtil { + + private static final ConcurrentMap cache = new ConcurrentReferenceHashMap<>(16, SOFT); + + public static boolean alreadyProcessed(Object deduplicationKey, long deduplicationDuration) { + AtomicBoolean alreadyProcessed = new AtomicBoolean(false); + cache.compute(deduplicationKey, (key, lastProcessedTs) -> { + if (lastProcessedTs != null) { + long passed = System.currentTimeMillis() - lastProcessedTs; + if (passed <= deduplicationDuration) { + alreadyProcessed.set(true); + return lastProcessedTs; + } + } + return System.currentTimeMillis(); + }); + return alreadyProcessed.get(); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/Dao.java b/dao/src/main/java/org/thingsboard/server/dao/Dao.java index e7290cdced..e912872496 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/Dao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/Dao.java @@ -39,7 +39,7 @@ public interface Dao { T saveAndFlush(TenantId tenantId, T t); - boolean removeById(TenantId tenantId, UUID id); + void removeById(TenantId tenantId, UUID id); void removeAllByIds(Collection ids); diff --git a/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java deleted file mode 100644 index 4dd0633420..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/JpaDaoConfig.java +++ /dev/null @@ -1,37 +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.dao; - -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.data.repository.config.BootstrapMode; -import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.thingsboard.server.dao.util.TbAutoConfiguration; - -/** - * @author Valerii Sosliuk - */ -@Configuration -@TbAutoConfiguration -@ComponentScan({"org.thingsboard.server.dao.sql", "org.thingsboard.server.dao.attributes", "org.thingsboard.server.dao.cache", "org.thingsboard.server.cache"}) -@EnableJpaRepositories(value = "org.thingsboard.server.dao.sql", bootstrapMode = BootstrapMode.LAZY) -@EntityScan("org.thingsboard.server.dao.model.sql") -@EnableTransactionManagement -public class JpaDaoConfig { - -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index 2c111151b3..dd967953ad 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -65,7 +65,7 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al @Override public AlarmComment saveAlarmComment(TenantId tenantId, AlarmComment alarmComment) { - log.debug("Deleting Alarm Comment: {}", alarmComment); + log.debug("Saving Alarm Comment: {}", alarmComment); alarmCommentDataValidator.validate(alarmComment, c -> tenantId); AlarmComment result = alarmCommentDao.save(tenantId, alarmComment); eventPublisher.publishEvent(DeleteEntityEvent.builder().tenantId(tenantId).entity(result) diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java index 0283fdb961..18e45d08fb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java @@ -38,15 +38,15 @@ public class AssetProfileCacheKey implements Serializable { this.defaultProfile = defaultProfile; } - public static AssetProfileCacheKey fromName(TenantId tenantId, String name) { + public static AssetProfileCacheKey forName(TenantId tenantId, String name) { return new AssetProfileCacheKey(tenantId, name, null, false); } - public static AssetProfileCacheKey fromId(AssetProfileId id) { + public static AssetProfileCacheKey forId(AssetProfileId id) { return new AssetProfileCacheKey(null, null, id, false); } - public static AssetProfileCacheKey defaultProfile(TenantId tenantId) { + public static AssetProfileCacheKey forDefaultProfile(TenantId tenantId) { return new AssetProfileCacheKey(tenantId, null, null, true); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCaffeineCache.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCaffeineCache.java index db812732e8..b37f84e649 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCaffeineCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCaffeineCache.java @@ -18,13 +18,13 @@ package org.thingsboard.server.dao.asset; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; -import org.thingsboard.server.cache.CaffeineTbTransactionalCache; +import org.thingsboard.server.cache.VersionedCaffeineTbCache; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.asset.AssetProfile; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) @Service("AssetProfileCache") -public class AssetProfileCaffeineCache extends CaffeineTbTransactionalCache { +public class AssetProfileCaffeineCache extends VersionedCaffeineTbCache { public AssetProfileCaffeineCache(CacheManager cacheManager) { super(cacheManager, CacheConstants.ASSET_PROFILE_CACHE); diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileEvictEvent.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileEvictEvent.java index a08ad2ad32..0cb1d35bf5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileEvictEvent.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileEvictEvent.java @@ -15,11 +15,16 @@ */ package org.thingsboard.server.dao.asset; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.TenantId; @Data +@RequiredArgsConstructor +@AllArgsConstructor public class AssetProfileEvictEvent { private final TenantId tenantId; @@ -27,5 +32,6 @@ public class AssetProfileEvictEvent { private final String oldName; private final AssetProfileId assetProfileId; private final boolean defaultProfile; + private AssetProfile savedAssetProfile; } 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 625bc16d43..cd2ee7a9a8 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 @@ -19,17 +19,18 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.redis.connection.RedisConnectionFactory; 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.TbJsonRedisSerializer; +import org.thingsboard.server.cache.VersionedRedisTbCache; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.asset.AssetProfile; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @Service("AssetProfileCache") -public class AssetProfileRedisCache extends RedisTbTransactionalCache { +public class AssetProfileRedisCache extends VersionedRedisTbCache { public AssetProfileRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { super(CacheConstants.ASSET_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJsonRedisSerializer<>(AssetProfile.class)); } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java index 6848c58d5c..95786f0a6a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java @@ -33,7 +33,7 @@ import org.thingsboard.server.common.data.id.HasId; 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.dao.entity.AbstractCachedEntityService; +import org.thingsboard.server.dao.entity.CachedVersionedEntityService; import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.exception.DataValidationException; @@ -53,7 +53,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId; @Service("AssetProfileDaoService") @Slf4j -public class AssetProfileServiceImpl extends AbstractCachedEntityService implements AssetProfileService { +public class AssetProfileServiceImpl extends CachedVersionedEntityService implements AssetProfileService { private static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; @@ -81,18 +81,20 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService keys = new ArrayList<>(2); - keys.add(AssetProfileCacheKey.fromName(event.getTenantId(), event.getNewName())); - if (event.getAssetProfileId() != null) { - keys.add(AssetProfileCacheKey.fromId(event.getAssetProfileId())); + List toEvict = new ArrayList<>(2); + toEvict.add(AssetProfileCacheKey.forName(event.getTenantId(), event.getNewName())); + if (event.getSavedAssetProfile() != null) { + cache.put(AssetProfileCacheKey.forId(event.getSavedAssetProfile().getId()), event.getSavedAssetProfile()); + } else if (event.getAssetProfileId() != null) { + toEvict.add(AssetProfileCacheKey.forId(event.getAssetProfileId())); } if (event.isDefaultProfile()) { - keys.add(AssetProfileCacheKey.defaultProfile(event.getTenantId())); + toEvict.add(AssetProfileCacheKey.forDefaultProfile(event.getTenantId())); } if (StringUtils.isNotEmpty(event.getOldName()) && !event.getOldName().equals(event.getNewName())) { - keys.add(AssetProfileCacheKey.fromName(event.getTenantId(), event.getOldName())); + toEvict.add(AssetProfileCacheKey.forName(event.getTenantId(), event.getOldName())); } - cache.evict(keys); + cache.evict(toEvict); } @Override @@ -104,8 +106,8 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService INCORRECT_ASSET_PROFILE_ID + id); - return cache.getOrFetchFromDB(AssetProfileCacheKey.fromId(assetProfileId), - () -> assetProfileDao.findById(tenantId, assetProfileId.getId()), true, putInCache); + return cache.get(AssetProfileCacheKey.forId(assetProfileId), + () -> assetProfileDao.findById(tenantId, assetProfileId.getId()), putInCache); } @Override @@ -117,7 +119,7 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService INCORRECT_ASSET_PROFILE_NAME + s); - return cache.getOrFetchFromDB(AssetProfileCacheKey.fromName(tenantId, profileName), + return cache.getOrFetchFromDB(AssetProfileCacheKey.forName(tenantId, profileName), () -> assetProfileDao.findByName(tenantId, profileName), false, putInCache); } @@ -147,7 +149,7 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService INCORRECT_TENANT_ID + id); - return cache.getAndPutInTransaction(AssetProfileCacheKey.defaultProfile(tenantId), + return cache.getAndPutInTransaction(AssetProfileCacheKey.forDefaultProfile(tenantId), () -> assetProfileDao.findDefaultAssetProfile(tenantId), true); } @@ -353,4 +355,5 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService { - AuditLog auditLog = auditLogDao.save(tenantId, auditLogEntry); - auditLogSink.logAction(auditLog); + try { + AuditLog auditLog = auditLogDao.save(tenantId, auditLogEntry); + auditLogSink.logAction(auditLog); + } catch (Throwable e) { + log.error("[{}] Failed to save audit log: {}", tenantId, auditLogEntry, e); + } return null; }); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsDataSource.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsDataSource.java new file mode 100644 index 0000000000..3ca6a20d44 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsDataSource.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@ConditionalOnProperty(value = "spring.datasource.events.enabled", havingValue = "true") +public @interface DedicatedEventsDataSource { +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java new file mode 100644 index 0000000000..e4a0b36100 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DedicatedEventsJpaDaoConfig.java @@ -0,0 +1,91 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.config; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.repository.config.BootstrapMode; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.support.TransactionTemplate; +import org.thingsboard.server.dao.model.sql.AuditLogEntity; +import org.thingsboard.server.dao.model.sql.ErrorEventEntity; +import org.thingsboard.server.dao.model.sql.LifecycleEventEntity; +import org.thingsboard.server.dao.model.sql.RuleChainDebugEventEntity; +import org.thingsboard.server.dao.model.sql.RuleNodeDebugEventEntity; +import org.thingsboard.server.dao.model.sql.StatisticsEventEntity; + +import javax.sql.DataSource; +import java.util.Objects; + +@DedicatedEventsDataSource +@Configuration +@EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql.event", "org.thingsboard.server.dao.sql.audit"}, + bootstrapMode = BootstrapMode.LAZY, + entityManagerFactoryRef = "eventsEntityManagerFactory", transactionManagerRef = "eventsTransactionManager") +public class DedicatedEventsJpaDaoConfig { + + public static final String EVENTS_PERSISTENCE_UNIT = "events"; + public static final String EVENTS_DATA_SOURCE = EVENTS_PERSISTENCE_UNIT + "DataSource"; + public static final String EVENTS_TRANSACTION_MANAGER = EVENTS_PERSISTENCE_UNIT + "TransactionManager"; + public static final String EVENTS_TRANSACTION_TEMPLATE = EVENTS_PERSISTENCE_UNIT + "TransactionTemplate"; + public static final String EVENTS_JDBC_TEMPLATE = EVENTS_PERSISTENCE_UNIT + "JdbcTemplate"; + + @Bean + @ConfigurationProperties("spring.datasource.events") + public DataSourceProperties eventsDataSourceProperties() { + return new DataSourceProperties(); + } + + @ConfigurationProperties(prefix = "spring.datasource.events.hikari") + @Bean(EVENTS_DATA_SOURCE) + public DataSource eventsDataSource(@Qualifier("eventsDataSourceProperties") DataSourceProperties eventsDataSourceProperties) { + return eventsDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean eventsEntityManagerFactory(@Qualifier(EVENTS_DATA_SOURCE) DataSource eventsDataSource, + EntityManagerFactoryBuilder builder) { + return builder + .dataSource(eventsDataSource) + .packages(LifecycleEventEntity.class, StatisticsEventEntity.class, ErrorEventEntity.class, RuleNodeDebugEventEntity.class, RuleChainDebugEventEntity.class, AuditLogEntity.class) + .persistenceUnit(EVENTS_PERSISTENCE_UNIT) + .build(); + } + + @Bean(EVENTS_TRANSACTION_MANAGER) + public JpaTransactionManager eventsTransactionManager(@Qualifier("eventsEntityManagerFactory") LocalContainerEntityManagerFactoryBean eventsEntityManagerFactory) { + return new JpaTransactionManager(Objects.requireNonNull(eventsEntityManagerFactory.getObject())); + } + + @Bean(EVENTS_TRANSACTION_TEMPLATE) + public TransactionTemplate eventsTransactionTemplate(@Qualifier(EVENTS_TRANSACTION_MANAGER) JpaTransactionManager eventsTransactionManager) { + return new TransactionTemplate(eventsTransactionManager); + } + + @Bean(EVENTS_JDBC_TEMPLATE) + public JdbcTemplate eventsJdbcTemplate(@Qualifier(EVENTS_DATA_SOURCE) DataSource eventsDataSource) { + return new JdbcTemplate(eventsDataSource); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java new file mode 100644 index 0000000000..ad6c398ea6 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDataSource.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@ConditionalOnProperty(value = "spring.datasource.events.enabled", havingValue = "false", matchIfMissing = true) +public @interface DefaultDataSource { +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/SqlTimeseriesDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java similarity index 56% rename from dao/src/main/java/org/thingsboard/server/dao/SqlTimeseriesDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java index 09553fb973..fd28735b79 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/SqlTimeseriesDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/DefaultDedicatedJpaDaoConfig.java @@ -13,22 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.config.BootstrapMode; -import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.thingsboard.server.dao.util.TbAutoConfiguration; +@DefaultDataSource @Configuration -@TbAutoConfiguration -@ComponentScan({"org.thingsboard.server.dao.sqlts.dictionary"}) -@EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.dictionary"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.dictionary"}) -@EnableTransactionManagement -public class SqlTimeseriesDaoConfig { +@EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql.event", "org.thingsboard.server.dao.sql.audit"}, bootstrapMode = BootstrapMode.LAZY) +public class DefaultDedicatedJpaDaoConfig { } diff --git a/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java new file mode 100644 index 0000000000..86c0ed4ea3 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/config/JpaDaoConfig.java @@ -0,0 +1,121 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.config; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.Primary; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.repository.config.BootstrapMode; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.support.TransactionTemplate; +import org.thingsboard.server.dao.sql.audit.AuditLogRepository; +import org.thingsboard.server.dao.sql.event.EventRepository; +import org.thingsboard.server.dao.util.TbAutoConfiguration; + +import javax.sql.DataSource; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Configuration +@TbAutoConfiguration +@ComponentScan({"org.thingsboard.server.dao.sql", "org.thingsboard.server.dao.attributes", "org.thingsboard.server.dao.sqlts.dictionary", "org.thingsboard.server.dao.cache", "org.thingsboard.server.cache"}) +@EnableJpaRepositories(value = {"org.thingsboard.server.dao.sql", "org.thingsboard.server.dao.sqlts.dictionary"}, + excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {EventRepository.class, AuditLogRepository.class}), + bootstrapMode = BootstrapMode.LAZY) +public class JpaDaoConfig { + + @Bean + @ConfigurationProperties("spring.datasource") + public DataSourceProperties dataSourceProperties() { + return new DataSourceProperties(); + } + + @Primary + @ConfigurationProperties(prefix = "spring.datasource.hikari") + @Bean + public DataSource dataSource(@Qualifier("dataSourceProperties") DataSourceProperties dataSourceProperties) { + return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); + } + + @Primary + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("dataSource") DataSource dataSource, + EntityManagerFactoryBuilder builder, + @Autowired(required = false) SqlTsLatestDaoConfig tsLatestDaoConfig, + @Autowired(required = false) SqlTsDaoConfig tsDaoConfig, + @Autowired(required = false) TimescaleDaoConfig timescaleDaoConfig, + @Autowired(required = false) TimescaleTsLatestDaoConfig timescaleTsLatestDaoConfig) { + List packages = new ArrayList<>(); + packages.add("org.thingsboard.server.dao.model.sql"); + packages.add("org.thingsboard.server.dao.model.sqlts.dictionary"); + if (tsLatestDaoConfig != null) { + packages.add("org.thingsboard.server.dao.model.sqlts.latest"); + } + if (tsDaoConfig != null) { + packages.add("org.thingsboard.server.dao.model.sqlts.ts"); + } + if (timescaleDaoConfig != null) { + packages.add("org.thingsboard.server.dao.model.sqlts.timescale"); + } + if (timescaleTsLatestDaoConfig != null) { + packages.add("org.thingsboard.server.dao.model.sqlts.latest"); + } + return builder + .dataSource(dataSource) + .packages(packages.toArray(String[]::new)) + .persistenceUnit("default") + .build(); + } + + @Primary + @Bean + public JpaTransactionManager transactionManager(@Qualifier("entityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactory) { + return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactory.getObject())); + } + + @Primary + @Bean + public TransactionTemplate transactionTemplate(@Qualifier("transactionManager") JpaTransactionManager transactionManager) { + return new TransactionTemplate(transactionManager); + } + + @Primary + @Bean + public JdbcTemplate jdbcTemplate(@Qualifier("dataSource") DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Primary + @Bean + public NamedParameterJdbcTemplate namedParameterJdbcTemplate(@Qualifier("dataSource") DataSource dataSource) { + return new NamedParameterJdbcTemplate(dataSource); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/SqlTsDaoConfig.java similarity index 89% rename from dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/SqlTsDaoConfig.java index bbd31846db..478dbde5d1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/SqlTsDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/SqlTsDaoConfig.java @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -28,7 +27,6 @@ import org.thingsboard.server.dao.util.TbAutoConfiguration; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sqlts.sql", "org.thingsboard.server.dao.sqlts.insert.sql"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.ts", "org.thingsboard.server.dao.sqlts.insert.sql"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.ts"}) @EnableTransactionManagement @SqlTsDao public class SqlTsDaoConfig { diff --git a/dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/SqlTsLatestDaoConfig.java similarity index 89% rename from dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/SqlTsLatestDaoConfig.java index 6fcf21a0a8..49ff2afdb4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/SqlTsLatestDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/SqlTsLatestDaoConfig.java @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -28,7 +27,6 @@ import org.thingsboard.server.dao.util.TbAutoConfiguration; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sqlts.sql"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.insert.latest.sql", "org.thingsboard.server.dao.sqlts.latest"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.latest"}) @EnableTransactionManagement @SqlTsLatestDao public class SqlTsLatestDaoConfig { diff --git a/dao/src/main/java/org/thingsboard/server/dao/TimescaleDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java similarity index 89% rename from dao/src/main/java/org/thingsboard/server/dao/TimescaleDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java index c134b88897..3c910778a2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/TimescaleDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleDaoConfig.java @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -28,7 +27,6 @@ import org.thingsboard.server.dao.util.TimescaleDBTsDao; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sqlts.timescale"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.timescale", "org.thingsboard.server.dao.sqlts.insert.timescale"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.timescale"}) @EnableTransactionManagement @TimescaleDBTsDao public class TimescaleDaoConfig { diff --git a/dao/src/main/java/org/thingsboard/server/dao/TimescaleTsLatestDaoConfig.java b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java similarity index 89% rename from dao/src/main/java/org/thingsboard/server/dao/TimescaleTsLatestDaoConfig.java rename to dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java index f0e74f1c3d..f6d1e49a6e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/TimescaleTsLatestDaoConfig.java +++ b/dao/src/main/java/org/thingsboard/server/dao/config/TimescaleTsLatestDaoConfig.java @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.dao; +package org.thingsboard.server.dao.config; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -28,7 +27,6 @@ import org.thingsboard.server.dao.util.TimescaleDBTsLatestDao; @TbAutoConfiguration @ComponentScan({"org.thingsboard.server.dao.sqlts.timescale"}) @EnableJpaRepositories(value = {"org.thingsboard.server.dao.sqlts.insert.latest.sql", "org.thingsboard.server.dao.sqlts.latest"}, bootstrapMode = BootstrapMode.LAZY) -@EntityScan({"org.thingsboard.server.dao.model.sqlts.latest"}) @EnableTransactionManagement @TimescaleDBTsLatestDao public class TimescaleTsLatestDaoConfig { diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java index dc2fb4c4aa..2067ef4a5d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java @@ -201,9 +201,9 @@ public class CustomerServiceImpl extends AbstractCachedEntityService implements DeviceCredentialsService { - @Autowired - private DeviceCredentialsDao deviceCredentialsDao; - - @Autowired - private DataValidator credentialsValidator; + private final DeviceCredentialsDao deviceCredentialsDao; + private final DeviceCredentialsDataValidator credentialsValidator; @TransactionalEventListener(classes = DeviceCredentialsEvictEvent.class) @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java index eca228891d..6df8f9907e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java @@ -41,19 +41,19 @@ public class DeviceProfileCacheKey implements Serializable { this.provisionDeviceKey = provisionDeviceKey; } - public static DeviceProfileCacheKey fromName(TenantId tenantId, String name) { + public static DeviceProfileCacheKey forName(TenantId tenantId, String name) { return new DeviceProfileCacheKey(tenantId, name, null, false, null); } - public static DeviceProfileCacheKey fromId(DeviceProfileId id) { + public static DeviceProfileCacheKey forId(DeviceProfileId id) { return new DeviceProfileCacheKey(null, null, id, false, null); } - public static DeviceProfileCacheKey defaultProfile(TenantId tenantId) { + public static DeviceProfileCacheKey forDefaultProfile(TenantId tenantId) { return new DeviceProfileCacheKey(tenantId, null, null, true, null); } - public static DeviceProfileCacheKey fromProvisionDeviceKey(String provisionDeviceKey) { + public static DeviceProfileCacheKey forProvisionKey(String provisionDeviceKey) { return new DeviceProfileCacheKey(null, null, null, false, provisionDeviceKey); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCaffeineCache.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCaffeineCache.java index d9bb2fec33..8343c8ba40 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCaffeineCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCaffeineCache.java @@ -18,13 +18,13 @@ package org.thingsboard.server.dao.device; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; -import org.thingsboard.server.cache.CaffeineTbTransactionalCache; +import org.thingsboard.server.cache.VersionedCaffeineTbCache; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.DeviceProfile; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) @Service("DeviceProfileCache") -public class DeviceProfileCaffeineCache extends CaffeineTbTransactionalCache { +public class DeviceProfileCaffeineCache extends VersionedCaffeineTbCache { public DeviceProfileCaffeineCache(CacheManager cacheManager) { super(cacheManager, CacheConstants.DEVICE_PROFILE_CACHE); diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileEvictEvent.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileEvictEvent.java index 2b5fc0a644..9de496566b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileEvictEvent.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileEvictEvent.java @@ -15,11 +15,16 @@ */ package org.thingsboard.server.dao.device; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.TenantId; @Data +@RequiredArgsConstructor +@AllArgsConstructor public class DeviceProfileEvictEvent { private final TenantId tenantId; @@ -28,5 +33,6 @@ public class DeviceProfileEvictEvent { private final DeviceProfileId deviceProfileId; private final boolean defaultProfile; private final String provisionDeviceKey; + private DeviceProfile savedDeviceProfile; } 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 eafcc5d166..15d16d4012 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 @@ -21,9 +21,9 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.SerializationException; 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.TbRedisSerializer; +import org.thingsboard.server.cache.VersionedRedisTbCache; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.util.ProtoUtils; @@ -31,7 +31,7 @@ import org.thingsboard.server.gen.transport.TransportProtos; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @Service("DeviceProfileCache") -public class DeviceProfileRedisCache extends RedisTbTransactionalCache { +public class DeviceProfileRedisCache extends VersionedRedisTbCache { public DeviceProfileRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { super(CacheConstants.DEVICE_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer() { @@ -50,4 +50,5 @@ public class DeviceProfileRedisCache extends RedisTbTransactionalCache implements DeviceProfileService { +@RequiredArgsConstructor +public class DeviceProfileServiceImpl extends CachedVersionedEntityService implements DeviceProfileService { private static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId "; @@ -87,7 +88,7 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService deviceProfileValidator; + private DeviceProfileDataValidator deviceProfileValidator; @Autowired private ImageService imageService; @@ -95,21 +96,23 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService keys = new ArrayList<>(2); - keys.add(DeviceProfileCacheKey.fromName(event.getTenantId(), event.getNewName())); - if (event.getDeviceProfileId() != null) { - keys.add(DeviceProfileCacheKey.fromId(event.getDeviceProfileId())); + List toEvict = new ArrayList<>(2); + toEvict.add(DeviceProfileCacheKey.forName(event.getTenantId(), event.getNewName())); + if (event.getSavedDeviceProfile() != null) { + cache.put(DeviceProfileCacheKey.forId(event.getSavedDeviceProfile().getId()), event.getSavedDeviceProfile()); + } else if (event.getDeviceProfileId() != null) { + toEvict.add(DeviceProfileCacheKey.forId(event.getDeviceProfileId())); } if (event.isDefaultProfile()) { - keys.add(DeviceProfileCacheKey.defaultProfile(event.getTenantId())); + toEvict.add(DeviceProfileCacheKey.forDefaultProfile(event.getTenantId())); } if (StringUtils.isNotEmpty(event.getOldName()) && !event.getOldName().equals(event.getNewName())) { - keys.add(DeviceProfileCacheKey.fromName(event.getTenantId(), event.getOldName())); + toEvict.add(DeviceProfileCacheKey.forName(event.getTenantId(), event.getOldName())); } if (StringUtils.isNotEmpty(event.getProvisionDeviceKey())) { - keys.add(DeviceProfileCacheKey.fromProvisionDeviceKey(event.getProvisionDeviceKey())); + toEvict.add(DeviceProfileCacheKey.forProvisionKey(event.getProvisionDeviceKey())); } - cache.evict(keys); + cache.evict(toEvict); } @Override @@ -121,8 +124,8 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService INCORRECT_DEVICE_PROFILE_ID + id); - return cache.getOrFetchFromDB(DeviceProfileCacheKey.fromId(deviceProfileId), - () -> deviceProfileDao.findById(tenantId, deviceProfileId.getId()), true, putInCache); + return cache.get(DeviceProfileCacheKey.forId(deviceProfileId), + () -> deviceProfileDao.findById(tenantId, deviceProfileId.getId()), putInCache); } @Override @@ -134,7 +137,7 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService INCORRECT_DEVICE_PROFILE_NAME + pn); - return cache.getOrFetchFromDB(DeviceProfileCacheKey.fromName(tenantId, profileName), + return cache.getOrFetchFromDB(DeviceProfileCacheKey.forName(tenantId, profileName), () -> deviceProfileDao.findByName(tenantId, profileName), true, putInCache); } @@ -142,7 +145,7 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService INCORRECT_PROVISION_DEVICE_KEY + dk); - return cache.getAndPutInTransaction(DeviceProfileCacheKey.fromProvisionDeviceKey(provisionDeviceKey), + return cache.getAndPutInTransaction(DeviceProfileCacheKey.forProvisionKey(provisionDeviceKey), () -> deviceProfileDao.findByProvisionDeviceKey(provisionDeviceKey), false); } @@ -179,7 +182,7 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService INCORRECT_TENANT_ID + id); - return cache.getAndPutInTransaction(DeviceProfileCacheKey.defaultProfile(tenantId), + return cache.getAndPutInTransaction(DeviceProfileCacheKey.forDefaultProfile(tenantId), () -> deviceProfileDao.findDefaultDeviceProfile(tenantId), true); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index 5b770845c1..2c80354923 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.device; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionalEventListener; @@ -68,7 +68,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.dao.device.provision.ProvisionFailedException; import org.thingsboard.server.dao.device.provision.ProvisionRequest; import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; -import org.thingsboard.server.dao.entity.AbstractCachedEntityService; +import org.thingsboard.server.dao.entity.CachedVersionedEntityService; import org.thingsboard.server.dao.entity.EntityCountService; import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent; @@ -76,8 +76,8 @@ import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; -import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; +import org.thingsboard.server.dao.service.validator.DeviceDataValidator; import org.thingsboard.server.dao.sql.JpaExecutorService; import org.thingsboard.server.dao.tenant.TenantService; @@ -94,38 +94,23 @@ import static org.thingsboard.server.dao.service.Validator.validateString; @Service("DeviceDaoService") @Slf4j -public class DeviceServiceImpl extends AbstractCachedEntityService implements DeviceService { +@RequiredArgsConstructor +public class DeviceServiceImpl extends CachedVersionedEntityService implements DeviceService { public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; public static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId "; - public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; public static final String INCORRECT_DEVICE_ID = "Incorrect deviceId "; public static final String INCORRECT_EDGE_ID = "Incorrect edgeId "; - @Autowired - private DeviceDao deviceDao; - - @Autowired - private DeviceCredentialsService deviceCredentialsService; - - @Autowired - private DeviceProfileService deviceProfileService; - - @Autowired - private EventService eventService; - - @Autowired - private TenantService tenantService; - - @Autowired - private DataValidator deviceValidator; - - @Autowired - private EntityCountService countService; - - @Autowired - private JpaExecutorService executor; + private final DeviceDao deviceDao; + private final DeviceCredentialsService deviceCredentialsService; + private final DeviceProfileService deviceProfileService; + private final EventService eventService; + private final TenantService tenantService; + private final DeviceDataValidator deviceValidator; + private final EntityCountService countService; + private final JpaExecutorService executor; @Override public DeviceInfo findDeviceInfoById(TenantId tenantId, DeviceId deviceId) { @@ -139,11 +124,11 @@ public class DeviceServiceImpl extends AbstractCachedEntityService INCORRECT_DEVICE_ID + id); if (TenantId.SYS_TENANT_ID.equals(tenantId)) { - return cache.getAndPutInTransaction(new DeviceCacheKey(deviceId), - () -> deviceDao.findById(tenantId, deviceId.getId()), true); + return cache.get(new DeviceCacheKey(deviceId), + () -> deviceDao.findById(tenantId, deviceId.getId())); } else { - return cache.getAndPutInTransaction(new DeviceCacheKey(tenantId, deviceId), - () -> deviceDao.findDeviceByTenantIdAndId(tenantId, deviceId.getId()), true); + return cache.get(new DeviceCacheKey(tenantId, deviceId), + () -> deviceDao.findDeviceByTenantIdAndId(tenantId, deviceId.getId())); } } @@ -251,6 +236,7 @@ public class DeviceServiceImpl extends AbstractCachedEntityService keys = new ArrayList<>(3); - keys.add(new DeviceCacheKey(event.getTenantId(), event.getNewName())); - if (event.getDeviceId() != null) { - keys.add(new DeviceCacheKey(event.getDeviceId())); - keys.add(new DeviceCacheKey(event.getTenantId(), event.getDeviceId())); - } + List toEvict = new ArrayList<>(3); + toEvict.add(new DeviceCacheKey(event.getTenantId(), event.getNewName())); if (StringUtils.isNotEmpty(event.getOldName()) && !event.getOldName().equals(event.getNewName())) { - keys.add(new DeviceCacheKey(event.getTenantId(), event.getOldName())); + toEvict.add(new DeviceCacheKey(event.getTenantId(), event.getOldName())); + } + Device savedDevice = event.getSavedDevice(); + if (savedDevice != null) { + cache.put(new DeviceCacheKey(event.getDeviceId()), savedDevice); + cache.put(new DeviceCacheKey(event.getTenantId(), event.getDeviceId()), savedDevice); + } else { + toEvict.add(new DeviceCacheKey(event.getDeviceId())); + toEvict.add(new DeviceCacheKey(event.getTenantId(), event.getDeviceId())); } - cache.evict(keys); + cache.evict(toEvict); } private DeviceData syncDeviceData(DeviceProfile deviceProfile, DeviceData deviceData) { 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 d4d3d2fb37..c03bc0a238 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 @@ -246,8 +246,8 @@ public class EdgeServiceImpl extends AbstractCachedEntityService extends AbstractCachedEntityService { + + @Autowired + protected VersionedTbCache cache; + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheValue.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheValue.java index 271d604e31..e02182b498 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheValue.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheValue.java @@ -19,6 +19,7 @@ import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.HasVersion; import java.io.Serializable; import java.util.List; @@ -26,11 +27,16 @@ import java.util.List; @Getter @EqualsAndHashCode @Builder -public class EntityViewCacheValue implements Serializable { +public class EntityViewCacheValue implements Serializable, HasVersion { private static final long serialVersionUID = 1959004642076413174L; private final EntityView entityView; private final List entityViews; + @Override + public Long getVersion() { + return entityView != null ? entityView.getVersion() : 0; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCaffeineCache.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCaffeineCache.java index 7ee5a1a725..0aec41493b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCaffeineCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCaffeineCache.java @@ -18,12 +18,12 @@ package org.thingsboard.server.dao.entityview; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; -import org.thingsboard.server.cache.CaffeineTbTransactionalCache; +import org.thingsboard.server.cache.VersionedCaffeineTbCache; import org.thingsboard.server.common.data.CacheConstants; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) @Service("EntityViewCache") -public class EntityViewCaffeineCache extends CaffeineTbTransactionalCache { +public class EntityViewCaffeineCache extends VersionedCaffeineTbCache { public EntityViewCaffeineCache(CacheManager cacheManager) { super(cacheManager, CacheConstants.ENTITY_VIEW_CACHE); diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewEvictEvent.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewEvictEvent.java index aac8167d50..2e81084a9e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewEvictEvent.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewEvictEvent.java @@ -15,21 +15,25 @@ */ package org.thingsboard.server.dao.entityview; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.RequiredArgsConstructor; +import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.TenantId; @Data @RequiredArgsConstructor +@AllArgsConstructor class EntityViewEvictEvent { private final TenantId tenantId; - private final EntityViewId id; + private final EntityViewId entityViewId; private final EntityId newEntityId; private final EntityId oldEntityId; private final String newName; private final String oldName; + private EntityView savedEntityView; } 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 8ce7f84b75..480540a78b 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 @@ -19,14 +19,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.redis.connection.RedisConnectionFactory; 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.TbJsonRedisSerializer; +import org.thingsboard.server.cache.VersionedRedisTbCache; import org.thingsboard.server.common.data.CacheConstants; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @Service("EntityViewCache") -public class EntityViewRedisCache extends RedisTbTransactionalCache { +public class EntityViewRedisCache extends VersionedRedisTbCache { public EntityViewRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { super(CacheConstants.ENTITY_VIEW_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJsonRedisSerializer<>(EntityViewCacheValue.class)); 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 d396fc3cfd..cbe6883b46 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 @@ -44,13 +44,13 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationTypeGroup; -import org.thingsboard.server.dao.entity.AbstractCachedEntityService; +import org.thingsboard.server.dao.entity.CachedVersionedEntityService; import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent; import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.exception.DataValidationException; -import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; +import org.thingsboard.server.dao.service.validator.EntityViewDataValidator; import org.thingsboard.server.dao.sql.JpaExecutorService; import java.util.ArrayList; @@ -69,7 +69,7 @@ import static org.thingsboard.server.dao.service.Validator.validateString; */ @Service("EntityViewDaoService") @Slf4j -public class EntityViewServiceImpl extends AbstractCachedEntityService implements EntityViewService { +public class EntityViewServiceImpl extends CachedVersionedEntityService implements EntityViewService { public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; @@ -80,7 +80,7 @@ public class EntityViewServiceImpl extends AbstractCachedEntityService entityViewValidator; + private EntityViewDataValidator entityViewValidator; @Autowired protected JpaExecutorService service; @@ -88,17 +88,21 @@ public class EntityViewServiceImpl extends AbstractCachedEntityService keys = new ArrayList<>(5); - keys.add(EntityViewCacheKey.byName(event.getTenantId(), event.getNewName())); - keys.add(EntityViewCacheKey.byId(event.getId())); - keys.add(EntityViewCacheKey.byEntityId(event.getTenantId(), event.getNewEntityId())); + List toEvict = new ArrayList<>(5); + toEvict.add(EntityViewCacheKey.byName(event.getTenantId(), event.getNewName())); + if (event.getSavedEntityView() != null) { + cache.put(EntityViewCacheKey.byId(event.getSavedEntityView().getId()), new EntityViewCacheValue(event.getSavedEntityView(), null)); + } else if (event.getEntityViewId() != null) { + toEvict.add(EntityViewCacheKey.byId(event.getEntityViewId())); + } + toEvict.add(EntityViewCacheKey.byEntityId(event.getTenantId(), event.getNewEntityId())); if (event.getOldEntityId() != null && !event.getOldEntityId().equals(event.getNewEntityId())) { - keys.add(EntityViewCacheKey.byEntityId(event.getTenantId(), event.getOldEntityId())); + toEvict.add(EntityViewCacheKey.byEntityId(event.getTenantId(), event.getOldEntityId())); } if (StringUtils.isNotEmpty(event.getOldName()) && !event.getOldName().equals(event.getNewName())) { - keys.add(EntityViewCacheKey.byName(event.getTenantId(), event.getOldName())); + toEvict.add(EntityViewCacheKey.byName(event.getTenantId(), event.getOldName())); } - cache.evict(keys); + cache.evict(toEvict); } @Override @@ -113,11 +117,11 @@ public class EntityViewServiceImpl extends AbstractCachedEntityService INCORRECT_ENTITY_VIEW_ID + id); - return cache.getOrFetchFromDB(EntityViewCacheKey.byId(entityViewId), - () -> entityViewDao.findById(tenantId, entityViewId.getId()) - , EntityViewCacheValue::getEntityView, v -> new EntityViewCacheValue(v, null), true, putInCache); + EntityViewCacheValue value = cache.get(EntityViewCacheKey.byId(entityViewId), () -> { + EntityView entityView = entityViewDao.findById(tenantId, entityViewId.getId()); + return new EntityViewCacheValue(entityView, null); + }, putInCache); + return value != null ? value.getEntityView() : null; } @Override @@ -233,7 +239,7 @@ public class EntityViewServiceImpl extends AbstractCachedEntityServiceINCORRECT_TENANT_ID + id); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); validateId(customerId, id -> INCORRECT_CUSTOMER_ID + id); validatePageLink(pageLink); return entityViewDao.findEntityViewsByTenantIdAndCustomerId(tenantId.getId(), diff --git a/dao/src/main/java/org/thingsboard/server/dao/event/EventDao.java b/dao/src/main/java/org/thingsboard/server/dao/event/EventDao.java index 6b3febf502..52335d87ec 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/event/EventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/event/EventDao.java @@ -101,5 +101,4 @@ public interface EventDao { */ void removeEvents(UUID tenantId, UUID entityId, EventFilter eventFilter, Long startTime, Long endTime); - void migrateEvents(long regularEventTs, long debugEventTs); } 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 02e1a15543..9f363ace96 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 @@ -22,6 +22,7 @@ import jakarta.persistence.MappedSuperclass; import lombok.Data; import org.apache.commons.lang3.StringUtils; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UUIDBased; @@ -48,6 +49,19 @@ public abstract class BaseSqlEntity implements BaseEntity { @Column(name = ModelConstants.CREATED_TIME_PROPERTY, updatable = false) protected long createdTime; + public BaseSqlEntity() { + } + + public BaseSqlEntity(BaseData domain) { + this.id = domain.getUuidId(); + this.createdTime = domain.getCreatedTime(); + } + + public BaseSqlEntity(BaseSqlEntity entity) { + this.id = entity.id; + this.createdTime = entity.createdTime; + } + @Override public UUID getUuid() { return id; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/BaseVersionedEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/BaseVersionedEntity.java index 6b98348de9..900fe2ed7f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/BaseVersionedEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/BaseVersionedEntity.java @@ -15,6 +15,47 @@ */ package org.thingsboard.server.dao.model; -public interface BaseVersionedEntity { - long getVersion(); +import jakarta.persistence.Column; +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.Version; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.thingsboard.server.common.data.BaseData; +import org.thingsboard.server.common.data.HasVersion; + +@Data +@EqualsAndHashCode(callSuper = true) +@MappedSuperclass +public abstract class BaseVersionedEntity extends BaseSqlEntity implements HasVersion { + + @Getter @Setter + @Version + @Column(name = ModelConstants.VERSION_PROPERTY) + protected Long version; + + public BaseVersionedEntity() { + super(); + } + + public BaseVersionedEntity(D domain) { + super(domain); + this.version = domain.getVersion(); + } + + public BaseVersionedEntity(BaseVersionedEntity entity) { + super(entity); + this.version = entity.version; + } + + @Override + public String toString() { + return "BaseVersionedEntity{" + + "id=" + id + + ", createdTime=" + createdTime + + ", version=" + version + + '}'; + } + } 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 2d3a2bdb94..27f1019a68 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 @@ -49,6 +49,7 @@ public class ModelConstants { public static final String SEARCH_TEXT_PROPERTY = "search_text"; public static final String ADDITIONAL_INFO_PROPERTY = "additional_info"; public static final String ENTITY_TYPE_PROPERTY = "entity_type"; + public static final String VERSION_PROPERTY = "version"; public static final String ENTITY_TYPE_COLUMN = ENTITY_TYPE_PROPERTY; public static final String TENANT_ID_COLUMN = "tenant_id"; 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 50fe1f7636..30c53c30e1 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 @@ -26,7 +26,6 @@ import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; 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.JsonConverter; @@ -40,7 +39,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TYPE @Data @EqualsAndHashCode(callSuper = true) @MappedSuperclass -public abstract class AbstractAlarmCommentEntity extends BaseSqlEntity implements BaseEntity { +public abstract class AbstractAlarmCommentEntity extends BaseSqlEntity { @Column(name = ALARM_COMMENT_ALARM_ID, columnDefinition = "uuid") private UUID alarmId; @@ -94,4 +93,5 @@ public abstract class AbstractAlarmCommentEntity extends alarmComment.setComment(comment); return alarmComment; } + } 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 4c488b3917..716e794511 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 @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonConverter; @@ -42,7 +42,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.EXTERNAL_ID_PROPER @Data @EqualsAndHashCode(callSuper = true) @MappedSuperclass -public abstract class AbstractAssetEntity extends BaseSqlEntity { +public abstract class AbstractAssetEntity extends BaseVersionedEntity { @Column(name = ASSET_TENANT_ID_PROPERTY) private UUID tenantId; @@ -73,11 +73,8 @@ public abstract class AbstractAssetEntity extends BaseSqlEntity super(); } - public AbstractAssetEntity(Asset asset) { - if (asset.getId() != null) { - this.setUuid(asset.getId().getId()); - } - this.setCreatedTime(asset.getCreatedTime()); + public AbstractAssetEntity(T asset) { + super(asset); if (asset.getTenantId() != null) { this.tenantId = asset.getTenantId().getId(); } @@ -97,8 +94,7 @@ public abstract class AbstractAssetEntity extends BaseSqlEntity } public AbstractAssetEntity(AssetEntity assetEntity) { - this.setId(assetEntity.getId()); - this.setCreatedTime(assetEntity.getCreatedTime()); + super(assetEntity); this.tenantId = assetEntity.getTenantId(); this.customerId = assetEntity.getCustomerId(); this.assetProfileId = assetEntity.getAssetProfileId(); @@ -112,6 +108,7 @@ public abstract class AbstractAssetEntity extends BaseSqlEntity protected Asset toAsset() { Asset asset = new Asset(new AssetId(id)); asset.setCreatedTime(createdTime); + asset.setVersion(version); if (tenantId != null) { asset.setTenantId(TenantId.fromUUID(tenantId)); } 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 1c0f47d062..3ce6d171dc 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 @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.OtaPackageId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonConverter; @@ -41,7 +41,7 @@ import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @MappedSuperclass -public abstract class AbstractDeviceEntity extends BaseSqlEntity { +public abstract class AbstractDeviceEntity extends BaseVersionedEntity { @Column(name = ModelConstants.DEVICE_TENANT_ID_PROPERTY, columnDefinition = "uuid") private UUID tenantId; @@ -83,11 +83,8 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti super(); } - public AbstractDeviceEntity(Device device) { - if (device.getId() != null) { - this.setUuid(device.getUuidId()); - } - this.setCreatedTime(device.getCreatedTime()); + public AbstractDeviceEntity(T device) { + super(device); if (device.getTenantId() != null) { this.tenantId = device.getTenantId().getId(); } @@ -113,9 +110,8 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti } } - public AbstractDeviceEntity(DeviceEntity deviceEntity) { - this.setId(deviceEntity.getId()); - this.setCreatedTime(deviceEntity.getCreatedTime()); + public AbstractDeviceEntity(AbstractDeviceEntity deviceEntity) { + super(deviceEntity); this.tenantId = deviceEntity.getTenantId(); this.customerId = deviceEntity.getCustomerId(); this.deviceProfileId = deviceEntity.getDeviceProfileId(); @@ -132,6 +128,7 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti protected Device toDevice() { Device device = new Device(new DeviceId(getUuid())); device.setCreatedTime(createdTime); + device.setVersion(version); if (tenantId != null) { device.setTenantId(TenantId.fromUUID(tenantId)); } 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 19907c8182..f02b33b65f 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 @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.id.CustomerId; 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.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonConverter; @@ -44,7 +44,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TYPE_PROPERTY @Data @EqualsAndHashCode(callSuper = true) @MappedSuperclass -public abstract class AbstractEdgeEntity extends BaseSqlEntity { +public abstract class AbstractEdgeEntity extends BaseVersionedEntity { @Column(name = EDGE_TENANT_ID_PROPERTY, columnDefinition = "uuid") private UUID tenantId; @@ -78,11 +78,8 @@ public abstract class AbstractEdgeEntity extends BaseSqlEntity extends BaseSqlEntity extends BaseSqlEntity extends BaseSqlEntity extends BaseSqlEntity { +public abstract class AbstractEntityViewEntity extends BaseVersionedEntity { @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY) private UUID entityId; @@ -89,11 +89,8 @@ public abstract class AbstractEntityViewEntity extends Bas super(); } - public AbstractEntityViewEntity(EntityView entityView) { - if (entityView.getId() != null) { - this.setUuid(entityView.getId().getId()); - } - this.setCreatedTime(entityView.getCreatedTime()); + public AbstractEntityViewEntity(T entityView) { + super(entityView); if (entityView.getEntityId() != null) { this.entityId = entityView.getEntityId().getId(); this.entityType = entityView.getEntityId().getEntityType(); @@ -120,8 +117,7 @@ public abstract class AbstractEntityViewEntity extends Bas } public AbstractEntityViewEntity(EntityViewEntity entityViewEntity) { - this.setId(entityViewEntity.getId()); - this.setCreatedTime(entityViewEntity.getCreatedTime()); + super(entityViewEntity); this.entityId = entityViewEntity.getEntityId(); this.entityType = entityViewEntity.getEntityType(); this.tenantId = entityViewEntity.getTenantId(); @@ -138,6 +134,7 @@ public abstract class AbstractEntityViewEntity extends Bas protected EntityView toEntityView() { EntityView entityView = new EntityView(new EntityViewId(getUuid())); entityView.setCreatedTime(createdTime); + entityView.setVersion(version); if (entityId != null) { entityView.setEntityId(EntityIdFactory.getByTypeAndUuid(entityType.name(), entityId)); @@ -163,4 +160,5 @@ public abstract class AbstractEntityViewEntity extends Bas } return entityView; } + } 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 845a196569..61fed6097e 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 @@ -24,7 +24,7 @@ import lombok.EqualsAndHashCode; 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.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonConverter; @@ -33,7 +33,7 @@ import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @MappedSuperclass -public abstract class AbstractTenantEntity extends BaseSqlEntity { +public abstract class AbstractTenantEntity extends BaseVersionedEntity { @Column(name = ModelConstants.TENANT_TITLE_PROPERTY) private String title; @@ -76,11 +76,8 @@ public abstract class AbstractTenantEntity extends BaseSqlEnti super(); } - public AbstractTenantEntity(Tenant tenant) { - if (tenant.getId() != null) { - this.setUuid(tenant.getId().getId()); - } - this.setCreatedTime(tenant.getCreatedTime()); + public AbstractTenantEntity(T tenant) { + super(tenant); this.title = tenant.getTitle(); this.region = tenant.getRegion(); this.country = tenant.getCountry(); @@ -98,8 +95,7 @@ public abstract class AbstractTenantEntity extends BaseSqlEnti } public AbstractTenantEntity(TenantEntity tenantEntity) { - this.setId(tenantEntity.getId()); - this.setCreatedTime(tenantEntity.getCreatedTime()); + super(tenantEntity); this.title = tenantEntity.getTitle(); this.region = tenantEntity.getRegion(); this.country = tenantEntity.getCountry(); @@ -117,6 +113,7 @@ public abstract class AbstractTenantEntity extends BaseSqlEnti protected Tenant toTenant() { Tenant tenant = new Tenant(TenantId.fromUUID(this.getUuid())); tenant.setCreatedTime(createdTime); + tenant.setVersion(version); tenant.setTitle(title); tenant.setRegion(region); tenant.setCountry(country); 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 65b5619104..d649d1e31a 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 @@ -22,7 +22,7 @@ import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.widget.BaseWidgetType; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import java.util.UUID; @@ -30,7 +30,7 @@ import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @MappedSuperclass -public abstract class AbstractWidgetTypeEntity extends BaseSqlEntity { +public abstract class AbstractWidgetTypeEntity extends BaseVersionedEntity { @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY) private UUID tenantId; @@ -51,11 +51,8 @@ public abstract class AbstractWidgetTypeEntity extends super(); } - public AbstractWidgetTypeEntity(BaseWidgetType widgetType) { - if (widgetType.getId() != null) { - this.setUuid(widgetType.getId().getId()); - } - this.setCreatedTime(widgetType.getCreatedTime()); + public AbstractWidgetTypeEntity(T widgetType) { + super(widgetType); if (widgetType.getTenantId() != null) { this.tenantId = widgetType.getTenantId().getId(); } @@ -66,8 +63,7 @@ public abstract class AbstractWidgetTypeEntity extends } public AbstractWidgetTypeEntity(AbstractWidgetTypeEntity widgetTypeEntity) { - this.setId(widgetTypeEntity.getId()); - this.setCreatedTime(widgetTypeEntity.getCreatedTime()); + super(widgetTypeEntity); this.tenantId = widgetTypeEntity.getTenantId(); this.fqn = widgetTypeEntity.getFqn(); this.name = widgetTypeEntity.getName(); @@ -78,6 +74,7 @@ public abstract class AbstractWidgetTypeEntity extends protected BaseWidgetType toBaseWidgetType() { BaseWidgetType widgetType = new BaseWidgetType(new WidgetTypeId(getUuid())); widgetType.setCreatedTime(createdTime); + widgetType.setVersion(version); if (tenantId != null) { widgetType.setTenantId(TenantId.fromUUID(tenantId)); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetInfoEntity.java index 264f41c226..73264a15df 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetInfoEntity.java @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; +import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetInfo; import java.util.HashMap; 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 ab9132e8cc..536da5b1ec 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 @@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import java.util.UUID; @@ -34,7 +34,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.ASSET_PROFILE_TABLE_NAME) -public final class AssetProfileEntity extends BaseSqlEntity { +public final class AssetProfileEntity extends BaseVersionedEntity { @Column(name = ModelConstants.ASSET_PROFILE_TENANT_ID_PROPERTY) private UUID tenantId; @@ -71,13 +71,10 @@ public final class AssetProfileEntity extends BaseSqlEntity { } public AssetProfileEntity(AssetProfile assetProfile) { - if (assetProfile.getId() != null) { - this.setUuid(assetProfile.getId().getId()); - } + super(assetProfile); if (assetProfile.getTenantId() != null) { this.tenantId = assetProfile.getTenantId().getId(); } - this.setCreatedTime(assetProfile.getCreatedTime()); this.name = assetProfile.getName(); this.image = assetProfile.getImage(); this.description = assetProfile.getDescription(); @@ -101,6 +98,7 @@ public final class AssetProfileEntity extends BaseSqlEntity { public AssetProfile toData() { AssetProfile assetProfile = new AssetProfile(new AssetProfileId(this.getUuid())); assetProfile.setCreatedTime(createdTime); + assetProfile.setVersion(version); if (tenantId != null) { assetProfile.setTenantId(TenantId.fromUUID(tenantId)); } 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 1e878e9dc5..85e697bb2b 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 @@ -149,4 +149,5 @@ public class AuditLogEntity extends BaseSqlEntity implements BaseEntit auditLog.setActionFailureDetails(this.actionFailureDetails); return auditLog; } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/CustomerEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/CustomerEntity.java index 569200e566..526f2a057a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/CustomerEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/CustomerEntity.java @@ -25,7 +25,7 @@ import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonConverter; @@ -35,7 +35,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.CUSTOMER_TABLE_NAME) -public final class CustomerEntity extends BaseSqlEntity { +public final class CustomerEntity extends BaseVersionedEntity { @Column(name = ModelConstants.CUSTOMER_TENANT_ID_PROPERTY) private UUID tenantId; @@ -82,10 +82,7 @@ public final class CustomerEntity extends BaseSqlEntity { } public CustomerEntity(Customer customer) { - if (customer.getId() != null) { - this.setUuid(customer.getId().getId()); - } - this.setCreatedTime(customer.getCreatedTime()); + super(customer); this.tenantId = customer.getTenantId().getId(); this.title = customer.getTitle(); this.country = customer.getCountry(); @@ -107,6 +104,7 @@ public final class CustomerEntity extends BaseSqlEntity { public Customer toData() { Customer customer = new Customer(new CustomerId(this.getUuid())); customer.setCreatedTime(createdTime); + customer.setVersion(version); customer.setTenantId(TenantId.fromUUID(tenantId)); customer.setTitle(title); customer.setCountry(country); 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 e5f4723699..c9e074ac7e 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 @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.ShortCustomerInfo; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonConverter; @@ -42,7 +42,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.DASHBOARD_TABLE_NAME) -public final class DashboardEntity extends BaseSqlEntity { +public final class DashboardEntity extends BaseVersionedEntity { private static final JavaType assignedCustomersType = JacksonUtil.constructCollectionType(HashSet.class, ShortCustomerInfo.class); @@ -77,10 +77,7 @@ public final class DashboardEntity extends BaseSqlEntity { } public DashboardEntity(Dashboard dashboard) { - if (dashboard.getId() != null) { - this.setUuid(dashboard.getId().getId()); - } - this.setCreatedTime(dashboard.getCreatedTime()); + super(dashboard); if (dashboard.getTenantId() != null) { this.tenantId = dashboard.getTenantId().getId(); } @@ -105,6 +102,7 @@ public final class DashboardEntity extends BaseSqlEntity { public Dashboard toData() { Dashboard dashboard = new Dashboard(new DashboardId(this.getUuid())); dashboard.setCreatedTime(this.getCreatedTime()); + dashboard.setVersion(version); if (tenantId != null) { dashboard.setTenantId(TenantId.fromUUID(tenantId)); } @@ -125,4 +123,5 @@ public final class DashboardEntity extends BaseSqlEntity { } return dashboard; } + } 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 067ad635df..93a1b1ad27 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 @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.ShortCustomerInfo; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import java.util.HashSet; @@ -39,7 +39,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.DASHBOARD_TABLE_NAME) -public class DashboardInfoEntity extends BaseSqlEntity { +public class DashboardInfoEntity extends BaseVersionedEntity { private static final JavaType assignedCustomersType = JacksonUtil.constructCollectionType(HashSet.class, ShortCustomerInfo.class); @@ -67,10 +67,7 @@ public class DashboardInfoEntity extends BaseSqlEntity { } public DashboardInfoEntity(DashboardInfo dashboardInfo) { - if (dashboardInfo.getId() != null) { - this.setUuid(dashboardInfo.getId().getId()); - } - this.setCreatedTime(dashboardInfo.getCreatedTime()); + super(dashboardInfo); if (dashboardInfo.getTenantId() != null) { this.tenantId = dashboardInfo.getTenantId().getId(); } @@ -91,6 +88,7 @@ public class DashboardInfoEntity extends BaseSqlEntity { public DashboardInfo toData() { DashboardInfo dashboardInfo = new DashboardInfo(new DashboardId(this.getUuid())); dashboardInfo.setCreatedTime(createdTime); + dashboardInfo.setVersion(version); if (tenantId != null) { dashboardInfo.setTenantId(TenantId.fromUUID(tenantId)); } 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 0b8b882304..edcaa745c7 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 @@ -26,8 +26,7 @@ import org.thingsboard.server.common.data.id.DeviceCredentialsId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; -import org.thingsboard.server.dao.model.BaseEntity; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import java.util.UUID; @@ -36,7 +35,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.DEVICE_CREDENTIALS_TABLE_NAME) -public final class DeviceCredentialsEntity extends BaseSqlEntity implements BaseEntity { +public final class DeviceCredentialsEntity extends BaseVersionedEntity { @Column(name = ModelConstants.DEVICE_CREDENTIALS_DEVICE_ID_PROPERTY) private UUID deviceId; @@ -56,10 +55,7 @@ public final class DeviceCredentialsEntity extends BaseSqlEntity { +public final class DeviceProfileEntity extends BaseVersionedEntity { @Column(name = ModelConstants.DEVICE_PROFILE_TENANT_ID_PROPERTY) private UUID tenantId; @@ -111,13 +111,10 @@ public final class DeviceProfileEntity extends BaseSqlEntity { } public DeviceProfileEntity(DeviceProfile deviceProfile) { - if (deviceProfile.getId() != null) { - this.setUuid(deviceProfile.getId().getId()); - } + super(deviceProfile); if (deviceProfile.getTenantId() != null) { this.tenantId = deviceProfile.getTenantId().getId(); } - this.setCreatedTime(deviceProfile.getCreatedTime()); this.name = deviceProfile.getName(); this.type = deviceProfile.getType(); this.image = deviceProfile.getImage(); @@ -152,6 +149,7 @@ public final class DeviceProfileEntity extends BaseSqlEntity { public DeviceProfile toData() { DeviceProfile deviceProfile = new DeviceProfile(new DeviceProfileId(this.getUuid())); deviceProfile.setCreatedTime(createdTime); + deviceProfile.setVersion(version); if (tenantId != null) { deviceProfile.setTenantId(TenantId.fromUUID(tenantId)); } @@ -187,4 +185,5 @@ public final class DeviceProfileEntity extends BaseSqlEntity { return deviceProfile; } + } 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 8e012ed0d1..6504eca4fb 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 @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.dao.DaoUtil; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonConverter; @@ -40,7 +40,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.RULE_CHAIN_TABLE_NAME) -public class RuleChainEntity extends BaseSqlEntity { +public class RuleChainEntity extends BaseVersionedEntity { @Column(name = ModelConstants.RULE_CHAIN_TENANT_ID_PROPERTY) private UUID tenantId; @@ -76,10 +76,7 @@ public class RuleChainEntity extends BaseSqlEntity { } public RuleChainEntity(RuleChain ruleChain) { - if (ruleChain.getId() != null) { - this.setUuid(ruleChain.getUuidId()); - } - this.setCreatedTime(ruleChain.getCreatedTime()); + super(ruleChain); this.tenantId = DaoUtil.getId(ruleChain.getTenantId()); this.name = ruleChain.getName(); this.type = ruleChain.getType(); @@ -99,6 +96,7 @@ public class RuleChainEntity extends BaseSqlEntity { public RuleChain toData() { RuleChain ruleChain = new RuleChain(new RuleChainId(this.getUuid())); ruleChain.setCreatedTime(createdTime); + ruleChain.setVersion(version); ruleChain.setTenantId(TenantId.fromUUID(tenantId)); ruleChain.setName(name); ruleChain.setType(type); @@ -114,4 +112,5 @@ public class RuleChainEntity extends BaseSqlEntity { } return ruleChain; } + } 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 abbf64fb08..87e901e930 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 @@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.security.Authority; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.util.mapping.JsonConverter; @@ -42,7 +42,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.USER_PG_HIBERNATE_TABLE_NAME) -public class UserEntity extends BaseSqlEntity { +public class UserEntity extends BaseVersionedEntity { @Column(name = ModelConstants.USER_TENANT_ID_PROPERTY) private UUID tenantId; @@ -74,10 +74,7 @@ public class UserEntity extends BaseSqlEntity { } public UserEntity(User user) { - if (user.getId() != null) { - this.setUuid(user.getId().getId()); - } - this.setCreatedTime(user.getCreatedTime()); + super(user); this.authority = user.getAuthority(); if (user.getTenantId() != null) { this.tenantId = user.getTenantId().getId(); @@ -96,6 +93,7 @@ public class UserEntity extends BaseSqlEntity { public User toData() { User user = new User(new UserId(this.getUuid())); user.setCreatedTime(createdTime); + user.setVersion(version); user.setAuthority(authority); if (tenantId != null) { user.setTenantId(TenantId.fromUUID(tenantId)); 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 264edefa7e..43e2bfd457 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 @@ -24,7 +24,7 @@ import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.widget.WidgetsBundle; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import java.util.UUID; @@ -33,7 +33,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.WIDGETS_BUNDLE_TABLE_NAME) -public final class WidgetsBundleEntity extends BaseSqlEntity { +public final class WidgetsBundleEntity extends BaseVersionedEntity { @Column(name = ModelConstants.WIDGETS_BUNDLE_TENANT_ID_PROPERTY) private UUID tenantId; @@ -64,10 +64,7 @@ public final class WidgetsBundleEntity extends BaseSqlEntity { } public WidgetsBundleEntity(WidgetsBundle widgetsBundle) { - if (widgetsBundle.getId() != null) { - this.setUuid(widgetsBundle.getId().getId()); - } - this.setCreatedTime(widgetsBundle.getCreatedTime()); + super(widgetsBundle); if (widgetsBundle.getTenantId() != null) { this.tenantId = widgetsBundle.getTenantId().getId(); } @@ -86,6 +83,7 @@ public final class WidgetsBundleEntity extends BaseSqlEntity { public WidgetsBundle toData() { WidgetsBundle widgetsBundle = new WidgetsBundle(new WidgetsBundleId(id)); widgetsBundle.setCreatedTime(createdTime); + widgetsBundle.setVersion(version); if (tenantId != null) { widgetsBundle.setTenantId(TenantId.fromUUID(tenantId)); } @@ -100,4 +98,5 @@ public final class WidgetsBundleEntity extends BaseSqlEntity { } return widgetsBundle; } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceCredentialsDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceCredentialsDataValidator.java index 5109a4e93f..8cf4a6fe42 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceCredentialsDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceCredentialsDataValidator.java @@ -16,6 +16,7 @@ package org.thingsboard.server.dao.service.validator; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.StringUtils; @@ -32,7 +33,7 @@ public class DeviceCredentialsDataValidator extends DataValidator, D> @Autowired protected JdbcTemplate jdbcTemplate; - protected abstract Class getEntityClass(); - - protected abstract JpaRepository getRepository(); + @PersistenceContext + private EntityManager entityManager; @Override @Transactional @@ -68,12 +72,38 @@ public abstract class JpaAbstractDao, D> entity.setUuid(uuid); entity.setCreatedTime(Uuids.unixTimestamp(uuid)); } - entity = doSave(entity, isNew); + try { + entity = doSave(entity, isNew); + } catch (OptimisticLockException e) { + throw new EntityVersionMismatchException((getEntityType() != null ? getEntityType().getNormalName() : "Entity") + " was already changed by someone else", e); + } return DaoUtil.getData(entity); } protected E doSave(E entity, boolean isNew) { - return getRepository().save(entity); + EntityManager entityManager = getEntityManager(); + if (isNew) { + if (entity instanceof HasVersion versionedEntity) { + versionedEntity.setVersion(1L); + } + entityManager.persist(entity); + } else { + if (entity instanceof HasVersion versionedEntity) { + if (versionedEntity.getVersion() == null) { + HasVersion existingEntity = entityManager.find(versionedEntity.getClass(), entity.getUuid()); + if (existingEntity != null) { + versionedEntity.setVersion(existingEntity.getVersion()); // manually resetting the version to latest to allow force overwrite of the entity + } else { + return doSave(entity, true); + } + } + entity = entityManager.merge(entity); + entityManager.flush(); + } else { + entity = entityManager.merge(entity); + } + } + return entity; } @Override @@ -111,16 +141,18 @@ public abstract class JpaAbstractDao, D> @Override @Transactional - public boolean removeById(TenantId tenantId, UUID id) { - getRepository().deleteById(id); + public void removeById(TenantId tenantId, UUID id) { + JpaRepository repository = getRepository(); + repository.deleteById(id); + repository.flush(); log.debug("Remove request: {}", id); - return !getRepository().existsById(id); } @Transactional public void removeAllByIds(Collection ids) { JpaRepository repository = getRepository(); ids.forEach(repository::deleteById); + repository.flush(); } @Override @@ -141,11 +173,23 @@ public abstract class JpaAbstractDao, D> } query += " ORDER BY id LIMIT ?"; - return jdbcTemplate.queryForList(query, UUID.class, params); + return getJdbcTemplate().queryForList(query, UUID.class, params); } protected String getTenantIdColumn() { return ModelConstants.TENANT_ID_COLUMN; } + protected EntityManager getEntityManager() { + return entityManager; + } + + protected JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } + + protected abstract Class getEntityClass(); + + protected abstract JpaRepository getRepository(); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java index 38cf02047f..6afb8b4ede 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java @@ -15,26 +15,16 @@ */ package org.thingsboard.server.dao.sql; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.util.SqlDao; @SqlDao public abstract class JpaPartitionedAbstractDao, D> extends JpaAbstractDao { - @PersistenceContext - private EntityManager entityManager; - @Override protected E doSave(E entity, boolean isNew) { createPartition(entity); - if (isNew) { - entityManager.persist(entity); - } else { - entity = entityManager.merge(entity); - } - return entity; + return super.doSave(entity, isNew); } public abstract void createPartition(E entity); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java new file mode 100644 index 0000000000..d40e1e5474 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/DedicatedJpaAuditLogDao.java @@ -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. + */ +package org.thingsboard.server.dao.sql.audit; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.thingsboard.server.common.data.audit.AuditLog; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.config.DedicatedEventsDataSource; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedEventsSqlPartitioningRepository; +import org.thingsboard.server.dao.util.SqlDao; + +import java.util.Collection; +import java.util.UUID; + +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_PERSISTENCE_UNIT; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_TRANSACTION_MANAGER; + +@DedicatedEventsDataSource +@Component +@SqlDao +public class DedicatedJpaAuditLogDao extends JpaAuditLogDao { + + @Autowired + @Qualifier(EVENTS_JDBC_TEMPLATE) + private JdbcTemplate jdbcTemplate; + @PersistenceContext(unitName = EVENTS_PERSISTENCE_UNIT) + private EntityManager entityManager; + + public DedicatedJpaAuditLogDao(AuditLogRepository auditLogRepository, DedicatedEventsSqlPartitioningRepository partitioningRepository) { + super(auditLogRepository, partitioningRepository); + } + + @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) + @Override + public AuditLog save(TenantId tenantId, AuditLog domain) { + return super.save(tenantId, domain); + } + + @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) + @Override + public AuditLog saveAndFlush(TenantId tenantId, AuditLog domain) { + return super.saveAndFlush(tenantId, domain); + } + + @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) + @Override + public void removeById(TenantId tenantId, UUID id) { + super.removeById(tenantId, id); + } + + @Transactional(transactionManager = EVENTS_TRANSACTION_MANAGER) + @Override + public void removeAllByIds(Collection ids) { + super.removeAllByIds(ids); + } + + @Override + protected EntityManager getEntityManager() { + return entityManager; + } + + @Override + protected JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java index f73cb95c27..7e859d1e8c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java @@ -19,7 +19,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; @@ -30,7 +29,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.audit.AuditLogDao; -import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.config.DefaultDataSource; import org.thingsboard.server.dao.model.sql.AuditLogEntity; import org.thingsboard.server.dao.sql.JpaPartitionedAbstractDao; import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; @@ -40,6 +39,9 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; +import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_TABLE_NAME; + +@DefaultDataSource @Component @SqlDao @RequiredArgsConstructor @@ -48,24 +50,9 @@ public class JpaAuditLogDao extends JpaPartitionedAbstractDao getEntityClass() { - return AuditLogEntity.class; - } - - @Override - protected JpaRepository getRepository() { - return auditLogRepository; - } @Override public PageData findAuditLogsByTenantIdAndEntityId(UUID tenantId, EntityId entityId, List actionTypes, TimePageLink pageLink) { @@ -124,12 +111,22 @@ public class JpaAuditLogDao extends JpaPartitionedAbstractDao getEntityClass() { + return AuditLogEntity.class; + } + + @Override + protected JpaRepository getRepository() { + return auditLogRepository; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java index 6510d3c415..7571c00b6a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java @@ -19,7 +19,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.security.DeviceCredentials; @@ -52,14 +51,6 @@ public class JpaDeviceCredentialsDao extends JpaAbstractDao implement return DaoUtil.getData(deviceRepository.findDeviceInfoById(deviceId)); } - @Override - @Transactional - public Device saveAndFlush(TenantId tenantId, Device device) { - Device result = this.save(tenantId, device); - deviceRepository.flush(); - return result; - } - @Override public PageData findDevicesByTenantId(UUID tenantId, PageLink pageLink) { if (StringUtils.isEmpty(pageLink.getTextSearch())) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java new file mode 100644 index 0000000000..65169dcbc7 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedEventInsertRepository.java @@ -0,0 +1,36 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.event; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.support.TransactionTemplate; +import org.thingsboard.server.dao.config.DedicatedEventsDataSource; + +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_TRANSACTION_TEMPLATE; + +@DedicatedEventsDataSource +@Repository +public class DedicatedEventInsertRepository extends EventInsertRepository { + + public DedicatedEventInsertRepository(@Qualifier(EVENTS_JDBC_TEMPLATE) JdbcTemplate jdbcTemplate, + @Qualifier(EVENTS_TRANSACTION_TEMPLATE) TransactionTemplate transactionTemplate) { + super(jdbcTemplate, transactionTemplate); + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.java new file mode 100644 index 0000000000..9b7af5e7f7 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/DedicatedJpaEventDao.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.dao.sql.event; + +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.stats.StatsFactory; +import org.thingsboard.server.dao.config.DedicatedEventsDataSource; +import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; +import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedEventsSqlPartitioningRepository; +import org.thingsboard.server.dao.util.SqlDao; + +@DedicatedEventsDataSource +@Component +@SqlDao +public class DedicatedJpaEventDao extends JpaBaseEventDao { + + public DedicatedJpaEventDao(EventPartitionConfiguration partitionConfiguration, + DedicatedEventsSqlPartitioningRepository partitioningRepository, + LifecycleEventRepository lcEventRepository, + StatisticsEventRepository statsEventRepository, + ErrorEventRepository errorEventRepository, + DedicatedEventInsertRepository eventInsertRepository, + RuleNodeDebugEventRepository ruleNodeDebugEventRepository, + RuleChainDebugEventRepository ruleChainDebugEventRepository, + ScheduledLogExecutorComponent logExecutor, + StatsFactory statsFactory) { + super(partitionConfiguration, partitioningRepository, lcEventRepository, statsEventRepository, + errorEventRepository, eventInsertRepository, ruleNodeDebugEventRepository, + ruleChainDebugEventRepository, logExecutor, statsFactory); + } + +} 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 faa5eb6562..962be57892 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 @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.sql.event; import jakarta.annotation.PostConstruct; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; @@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.event.LifecycleEvent; import org.thingsboard.server.common.data.event.RuleChainDebugEvent; import org.thingsboard.server.common.data.event.RuleNodeDebugEvent; import org.thingsboard.server.common.data.event.StatisticsEvent; +import org.thingsboard.server.dao.config.DefaultDataSource; import org.thingsboard.server.dao.util.SqlDao; import java.sql.PreparedStatement; @@ -44,9 +45,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import java.util.stream.Collectors; +@DefaultDataSource @Repository @Transactional @SqlDao +@RequiredArgsConstructor public class EventInsertRepository { private static final ThreadLocal PATTERN_THREAD_LOCAL = ThreadLocal.withInitial(() -> Pattern.compile(String.valueOf(Character.MIN_VALUE))); @@ -55,11 +58,8 @@ public class EventInsertRepository { private final Map insertStmtMap = new ConcurrentHashMap<>(); - @Autowired - protected JdbcTemplate jdbcTemplate; - - @Autowired - private TransactionTemplate transactionTemplate; + private final JdbcTemplate jdbcTemplate; + private final TransactionTemplate transactionTemplate; @Value("${sql.remove_null_chars:true}") private boolean removeNullChars; @@ -236,4 +236,5 @@ public class EventInsertRepository { } return strValue; } + } 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 33e7567664..b8d5083402 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 @@ -19,8 +19,8 @@ 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.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; @@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.stats.StatsFactory; import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.config.DefaultDataSource; import org.thingsboard.server.dao.event.EventDao; import org.thingsboard.server.dao.model.sql.EventEntity; import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; @@ -54,46 +55,23 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; -/** - * Created by Valerii Sosliuk on 5/3/2017. - */ -@Slf4j +@DefaultDataSource @Component @SqlDao +@RequiredArgsConstructor +@Slf4j public class JpaBaseEventDao implements EventDao { - @Autowired - private EventPartitionConfiguration partitionConfiguration; - - @Autowired - private SqlPartitioningRepository partitioningRepository; - - @Autowired - private LifecycleEventRepository lcEventRepository; - - @Autowired - private StatisticsEventRepository statsEventRepository; - - @Autowired - private ErrorEventRepository errorEventRepository; - - @Autowired - private EventInsertRepository eventInsertRepository; - - @Autowired - private EventCleanupRepository eventCleanupRepository; - - @Autowired - private RuleNodeDebugEventRepository ruleNodeDebugEventRepository; - - @Autowired - private RuleChainDebugEventRepository ruleChainDebugEventRepository; - - @Autowired - ScheduledLogExecutorComponent logExecutor; - - @Autowired - private StatsFactory statsFactory; + private final EventPartitionConfiguration partitionConfiguration; + private final SqlPartitioningRepository partitioningRepository; + private final LifecycleEventRepository lcEventRepository; + private final StatisticsEventRepository statsEventRepository; + private final ErrorEventRepository errorEventRepository; + private final EventInsertRepository eventInsertRepository; + private final RuleNodeDebugEventRepository ruleNodeDebugEventRepository; + private final RuleChainDebugEventRepository ruleChainDebugEventRepository; + private final ScheduledLogExecutorComponent logExecutor; + private final StatsFactory statsFactory; @Value("${sql.events.batch_size:10000}") private int batchSize; @@ -223,11 +201,6 @@ public class JpaBaseEventDao implements EventDao { } } - @Override - public void migrateEvents(long regularEventTs, long debugEventTs) { - eventCleanupRepository.migrateEvents(regularEventTs, debugEventTs); - } - private PageData findEventByFilter(UUID tenantId, UUID entityId, RuleChainDebugEventFilter eventFilter, TimePageLink pageLink) { return DaoUtil.toPageData( ruleChainDebugEventRepository.findEvents( @@ -402,7 +375,7 @@ public class JpaBaseEventDao implements EventDao { if (regularEventExpTs > 0) { log.info("Going to cleanup regular events with exp time: {}", regularEventExpTs); if (cleanupDb) { - eventCleanupRepository.cleanupEvents(regularEventExpTs, false); + cleanupEvents(regularEventExpTs, false); } else { cleanupPartitionsCache(regularEventExpTs, false); } @@ -410,13 +383,25 @@ public class JpaBaseEventDao implements EventDao { if (debugEventExpTs > 0) { log.info("Going to cleanup debug events with exp time: {}", debugEventExpTs); if (cleanupDb) { - eventCleanupRepository.cleanupEvents(debugEventExpTs, true); + cleanupEvents(debugEventExpTs, true); } else { cleanupPartitionsCache(debugEventExpTs, true); } } } + private void cleanupEvents(long eventExpTime, boolean debug) { + for (EventType eventType : EventType.values()) { + if (eventType.isDebug() == debug) { + cleanupPartitions(eventType, eventExpTime); + } + } + } + + private void cleanupPartitions(EventType eventType, long eventExpTime) { + partitioningRepository.dropPartitionsBefore(eventType.getTable(), eventExpTime, partitionConfiguration.getPartitionSizeInMs(eventType)); + } + private void cleanupPartitionsCache(long expTime, boolean isDebug) { for (EventType eventType : EventType.values()) { if (eventType.isDebug() == isDebug) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java deleted file mode 100644 index d1e8aa380f..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/SqlEventCleanupRepository.java +++ /dev/null @@ -1,101 +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.dao.sql.event; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.DataAccessException; -import org.springframework.stereotype.Repository; -import org.thingsboard.server.common.data.event.EventType; -import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService; -import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; - -import java.util.concurrent.TimeUnit; - - -@Slf4j -@Repository -public class SqlEventCleanupRepository extends JpaAbstractDaoListeningExecutorService implements EventCleanupRepository { - - @Autowired - private EventPartitionConfiguration partitionConfiguration; - @Autowired - private SqlPartitioningRepository partitioningRepository; - - @Override - public void cleanupEvents(long eventExpTime, boolean debug) { - for (EventType eventType : EventType.values()) { - if (eventType.isDebug() == debug) { - cleanupEvents(eventType, eventExpTime); - } - } - } - - @Override - public void migrateEvents(long regularEventTs, long debugEventTs) { - regularEventTs = Math.max(regularEventTs, 1480982400000L); - debugEventTs = Math.max(debugEventTs, 1480982400000L); - - callMigrateFunctionByPartitions("regular", "migrate_regular_events", regularEventTs, partitionConfiguration.getRegularPartitionSizeInHours()); - callMigrateFunctionByPartitions("debug", "migrate_debug_events", debugEventTs, partitionConfiguration.getDebugPartitionSizeInHours()); - - try { - jdbcTemplate.execute("DROP PROCEDURE IF EXISTS migrate_regular_events(bigint, bigint, int)"); - jdbcTemplate.execute("DROP PROCEDURE IF EXISTS migrate_debug_events(bigint, bigint, int)"); - jdbcTemplate.execute("DROP TABLE IF EXISTS event"); - } catch (DataAccessException e) { - log.error("Error occurred during drop of the `events` table", e); - throw e; - } - } - - private void callMigrateFunctionByPartitions(String logTag, String functionName, long startTs, int partitionSizeInHours) { - long currentTs = System.currentTimeMillis(); - var regularPartitionStepInMs = TimeUnit.HOURS.toMillis(partitionSizeInHours); - long numberOfPartitions = (currentTs - startTs) / regularPartitionStepInMs; - if (numberOfPartitions > 1000) { - log.error("Please adjust your {} events partitioning configuration. " + - "Configuration with partition size of {} hours and corresponding TTL will use {} (>1000) partitions which is not recommended!", - logTag, partitionSizeInHours, numberOfPartitions); - throw new RuntimeException("Please adjust your " + logTag + " events partitioning configuration. " + - "Configuration with partition size of " + partitionSizeInHours + " hours and corresponding TTL will use " + - +numberOfPartitions + " (>1000) partitions which is not recommended!"); - } - while (startTs < currentTs) { - var endTs = startTs + regularPartitionStepInMs; - log.info("Migrate {} events for time period: [{},{}]", logTag, startTs, endTs); - callMigrateFunction(functionName, startTs, startTs + regularPartitionStepInMs, partitionSizeInHours); - startTs = endTs; - } - log.info("Migrate {} events done.", logTag); - } - - private void callMigrateFunction(String functionName, long startTs, long endTs, int partitionSizeInHours) { - try { - jdbcTemplate.update("CALL " + functionName + "(?, ?, ?)", startTs, endTs, partitionSizeInHours); - } catch (DataAccessException e) { - if (e.getMessage() == null || !e.getMessage().contains("relation \"event\" does not exist")) { - log.error("[{}] SQLException occurred during execution of {} with parameters {} and {}", functionName, startTs, partitionSizeInHours, e); - throw new RuntimeException(e); - } - } - } - - private void cleanupEvents(EventType eventType, long eventExpTime) { - partitioningRepository.dropPartitionsBefore(eventType.getTable(), eventExpTime, partitionConfiguration.getPartitionSizeInMs(eventType)); - } - -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/dictionary/JpaKeyDictionaryDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/dictionary/JpaKeyDictionaryDao.java index 870c0bc505..b01d1c4ea0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/dictionary/JpaKeyDictionaryDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/dictionary/JpaKeyDictionaryDao.java @@ -15,11 +15,13 @@ */ package org.thingsboard.server.dao.sqlts.dictionary; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.hibernate.exception.ConstraintViolationException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.dao.dictionary.KeyDictionaryDao; import org.thingsboard.server.dao.model.sqlts.dictionary.KeyDictionaryCompositeKey; import org.thingsboard.server.dao.model.sqlts.dictionary.KeyDictionaryEntry; @@ -34,14 +36,15 @@ import java.util.concurrent.locks.ReentrantLock; @Component @Slf4j @SqlDao +@RequiredArgsConstructor public class JpaKeyDictionaryDao extends JpaAbstractDaoListeningExecutorService implements KeyDictionaryDao { - private final ConcurrentMap keyDictionaryMap = new ConcurrentHashMap<>(); - protected static final ReentrantLock creationLock = new ReentrantLock(); + private final KeyDictionaryRepository keyDictionaryRepository; - @Autowired - private KeyDictionaryRepository keyDictionaryRepository; + private final ConcurrentMap keyDictionaryMap = new ConcurrentHashMap<>(); + private static final ReentrantLock creationLock = new ReentrantLock(); + @Transactional(propagation = Propagation.NOT_SUPPORTED) @Override public Integer getOrSaveKeyId(String strKey) { Integer keyId = keyDictionaryMap.get(strKey); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedEventsSqlPartitioningRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedEventsSqlPartitioningRepository.java new file mode 100644 index 0000000000..7e1be6bbd9 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/DedicatedEventsSqlPartitioningRepository.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.server.dao.sqlts.insert.sql; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.thingsboard.server.dao.config.DedicatedEventsDataSource; +import org.thingsboard.server.dao.timeseries.SqlPartition; + +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_JDBC_TEMPLATE; +import static org.thingsboard.server.dao.config.DedicatedEventsJpaDaoConfig.EVENTS_TRANSACTION_MANAGER; + +@DedicatedEventsDataSource +@Repository +public class DedicatedEventsSqlPartitioningRepository extends SqlPartitioningRepository { + + @Autowired + @Qualifier(EVENTS_JDBC_TEMPLATE) + private JdbcTemplate jdbcTemplate; + + @Transactional(propagation = Propagation.NOT_SUPPORTED, transactionManager = EVENTS_TRANSACTION_MANAGER) + @Override + public void save(SqlPartition partition) { + super.save(partition); + } + + @Transactional(propagation = Propagation.NOT_SUPPORTED, transactionManager = EVENTS_TRANSACTION_MANAGER) + @Override + public void createPartitionIfNotExists(String table, long entityTs, long partitionDurationMs) { + super.createPartitionIfNotExists(table, entityTs, partitionDurationMs); + } + + @Override + protected JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java index 83a7415780..0f3922e070 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java @@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @@ -32,6 +33,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; +@Primary @Repository @Slf4j public class SqlPartitioningRepository { @@ -49,7 +51,7 @@ public class SqlPartitioningRepository { @Transactional(propagation = Propagation.NOT_SUPPORTED) public void save(SqlPartition partition) { - jdbcTemplate.execute(partition.getQuery()); + getJdbcTemplate().execute(partition.getQuery()); } @Transactional(propagation = Propagation.NOT_SUPPORTED) // executing non-transactionally, so that parent transaction is not aborted on partition save error @@ -119,8 +121,8 @@ public class SqlPartitioningRepository { String dropStmtStr = "DROP TABLE " + tablePartition; try { - jdbcTemplate.execute(detachPsqlStmtStr); - jdbcTemplate.execute(dropStmtStr); + getJdbcTemplate().execute(detachPsqlStmtStr); + getJdbcTemplate().execute(dropStmtStr); return true; } catch (DataAccessException e) { log.error("[{}] Error occurred trying to detach and drop the partition {} ", table, partitionTs, e); @@ -134,7 +136,7 @@ public class SqlPartitioningRepository { public List fetchPartitions(String table) { List partitions = new ArrayList<>(); - List partitionsTables = jdbcTemplate.queryForList(SELECT_PARTITIONS_STMT, String.class, table); + List partitionsTables = getJdbcTemplate().queryForList(SELECT_PARTITIONS_STMT, String.class, table); for (String partitionTableName : partitionsTables) { String partitionTsStr = partitionTableName.substring(table.length() + 1); try { @@ -153,7 +155,7 @@ public class SqlPartitioningRepository { private synchronized int getCurrentServerVersion() { if (currentServerVersion == null) { try { - currentServerVersion = jdbcTemplate.queryForObject("SELECT current_setting('server_version_num')", Integer.class); + currentServerVersion = getJdbcTemplate().queryForObject("SELECT current_setting('server_version_num')", Integer.class); } catch (Exception e) { log.warn("Error occurred during fetch of the server version", e); } @@ -164,4 +166,8 @@ public class SqlPartitioningRepository { return currentServerVersion; } + protected JdbcTemplate getJdbcTemplate() { + return jdbcTemplate; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java index 34602d81b3..f64ccf4970 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 @@ -17,6 +17,9 @@ package org.thingsboard.server.dao.user; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.BooleanNode; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.LongNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.ListenableFuture; import lombok.RequiredArgsConstructor; @@ -411,16 +414,11 @@ public class UserServiceImpl extends AbstractCachedEntityService d.getId().equals(savedDevice.getId()) - && d.getTenantId().equals(tenantId) - && d.getLabel().equals(savedDevice.getLabel()) + && d.getTenantId().equals(tenantId) + && d.getLabel().equals(savedDevice.getLabel()) ) ); @@ -1004,9 +1004,9 @@ public class DeviceServiceTest extends AbstractServiceTest { deviceInfosWithLabel.stream() .anyMatch( d -> d.getId().equals(savedDevice.getId()) - && d.getTenantId().equals(tenantId) - && d.getDeviceProfileName().equals(savedDevice.getType()) - && d.getLabel().equals(savedDevice.getLabel()) + && d.getTenantId().equals(tenantId) + && d.getDeviceProfileName().equals(savedDevice.getType()) + && d.getLabel().equals(savedDevice.getLabel()) ) ); @@ -1072,4 +1072,5 @@ public class DeviceServiceTest extends AbstractServiceTest { ) ); } + } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedEventsDataSource.java b/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedEventsDataSource.java new file mode 100644 index 0000000000..cb765c29d0 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/event/sql/EventServiceSqlTest_DedicatedEventsDataSource.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.service.event.sql; + +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + +@DaoSqlTest +@TestPropertySource(properties = { + "spring.datasource.events.enabled=true", + "spring.datasource.events.url=${spring.datasource.url}", + "spring.datasource.events.driverClassName=${spring.datasource.driverClassName}" +}) +public class EventServiceSqlTest_DedicatedEventsDataSource extends EventServiceSqlTest { +} diff --git a/docker/docker-compose.redis-cluster.yml b/docker/docker-compose.redis-cluster.yml index 7b5d6d6dde..cb41207701 100644 --- a/docker/docker-compose.redis-cluster.yml +++ b/docker/docker-compose.redis-cluster.yml @@ -18,6 +18,7 @@ version: '3.0' services: # Redis cluster +# The latest version of Redis compatible with ThingsBoard is 7.2 redis-node-0: image: bitnami/redis-cluster:7.2 volumes: diff --git a/docker/docker-compose.redis-sentinel.yml b/docker/docker-compose.redis-sentinel.yml index a131bc7df9..5cb83afe15 100644 --- a/docker/docker-compose.redis-sentinel.yml +++ b/docker/docker-compose.redis-sentinel.yml @@ -18,6 +18,7 @@ version: '3.0' services: # Redis sentinel + # The latest version of Redis compatible with ThingsBoard is 7.2 redis-master: image: 'bitnami/redis:7.2' volumes: diff --git a/docker/docker-compose.redis.yml b/docker/docker-compose.redis.yml index 16b16d4a8e..cf0930c68a 100644 --- a/docker/docker-compose.redis.yml +++ b/docker/docker-compose.redis.yml @@ -18,6 +18,7 @@ version: '3.0' services: # Redis standalone +# The latest version of Redis compatible with ThingsBoard is 7.2 redis: restart: always image: bitnami/redis:7.2 diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/data/Latencies.java b/monitoring/src/main/java/org/thingsboard/monitoring/data/Latencies.java index ee21b36c53..4ab9d3c457 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/data/Latencies.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/data/Latencies.java @@ -17,8 +17,8 @@ package org.thingsboard.monitoring.data; public class Latencies { - public static final String WS_UPDATE = "wsUpdate"; public static final String WS_CONNECT = "wsConnect"; + public static final String WS_SUBSCRIBE = "wsSubscribe"; public static final String LOG_IN = "logIn"; public static String request(String key) { diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/service/BaseMonitoringService.java b/monitoring/src/main/java/org/thingsboard/monitoring/service/BaseMonitoringService.java index 7df767caef..c667c5b7ac 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/service/BaseMonitoringService.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/service/BaseMonitoringService.java @@ -100,7 +100,10 @@ public abstract class BaseMonitoringService, T ext reporter.reportLatency(Latencies.LOG_IN, stopWatch.getTime()); try (WsClient wsClient = wsClientFactory.createClient(accessToken)) { + stopWatch.start(); wsClient.subscribeForTelemetry(devices, TransportHealthChecker.TEST_TELEMETRY_KEY).waitForReply(); + reporter.reportLatency(Latencies.WS_SUBSCRIBE, stopWatch.getTime()); + for (BaseHealthChecker healthChecker : healthCheckers) { check(healthChecker, wsClient); } diff --git a/msa/black-box-tests/src/test/resources/docker-compose.redis-ssl.yml b/msa/black-box-tests/src/test/resources/docker-compose.redis-ssl.yml index 0407aa3f8c..3163921be6 100644 --- a/msa/black-box-tests/src/test/resources/docker-compose.redis-ssl.yml +++ b/msa/black-box-tests/src/test/resources/docker-compose.redis-ssl.yml @@ -18,6 +18,7 @@ version: '3.0' services: # Redis standalone +# The latest version of Redis compatible with ThingsBoard is 7.2 redis: restart: always image: bitnami/redis:7.2 diff --git a/pom.xml b/pom.xml index 5b6f30bef8..09cf0393b7 100755 --- a/pom.xml +++ b/pom.xml @@ -2097,10 +2097,6 @@ io.jsonwebtoken jjwt-impl - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java index d00b287cef..6b07d41a42 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java @@ -67,6 +67,10 @@ public class TbLogNode implements TbNode { @Override public void onMsg(TbContext ctx, TbMsg msg) { + if (!log.isInfoEnabled()) { + ctx.tellSuccess(msg); + return; + } if (standard) { logStandard(ctx, msg); return; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java index 62ed28fb04..537318fa75 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java @@ -129,7 +129,7 @@ public class TbPubSubNode extends TbAbstractExternalNode { return TbMsg.transformMsgMetadata(origMsg, metaData); } - private Publisher initPubSubClient(TbContext ctx) throws IOException { + Publisher initPubSubClient(TbContext ctx) throws IOException { ProjectTopicName topicName = ProjectTopicName.of(config.getProjectId(), config.getTopicName()); ServiceAccountCredentials credentials = ServiceAccountCredentials.fromStream( diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java index fa07e7c06d..89b6e1c1d9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java @@ -104,7 +104,7 @@ public class TbKafkaNode extends TbAbstractExternalNode { addMetadataKeyValuesAsKafkaHeaders = BooleanUtils.toBooleanDefaultIfNull(config.isAddMetadataKeyValuesAsKafkaHeaders(), false); toBytesCharset = config.getKafkaHeadersCharset() != null ? Charset.forName(config.getKafkaHeadersCharset()) : StandardCharsets.UTF_8; try { - this.producer = new KafkaProducer<>(properties); + this.producer = getKafkaProducer(properties); Thread ioThread = (Thread) ReflectionUtils.getField(IO_THREAD_FIELD, producer); ioThread.setUncaughtExceptionHandler((thread, throwable) -> { if (throwable instanceof ThingsboardKafkaClientError) { @@ -117,6 +117,10 @@ public class TbKafkaNode extends TbAbstractExternalNode { } } + KafkaProducer getKafkaProducer(Properties properties) { + return new KafkaProducer<>(properties); + } + @Override public void onMsg(TbContext ctx, TbMsg msg) { String topic = TbNodeUtils.processPattern(config.getTopicPattern(), msg); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java index 2baf26206f..c909a44a27 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java @@ -125,7 +125,7 @@ public class TbMqttNode extends TbAbstractExternalNode { config.setCleanSession(this.mqttNodeConfiguration.isCleanSession()); prepareMqttClientConfig(config); - MqttClient client = MqttClient.create(config, null, ctx.getExternalCallExecutor()); + MqttClient client = getMqttClient(ctx, config); client.setEventLoop(ctx.getSharedEventLoop()); Promise connectFuture = client.connect(this.mqttNodeConfiguration.getHost(), this.mqttNodeConfiguration.getPort()); MqttConnectResult result; @@ -146,7 +146,11 @@ public class TbMqttNode extends TbAbstractExternalNode { return client; } - protected void prepareMqttClientConfig(MqttClientConfig config) throws SSLException { + MqttClient getMqttClient(TbContext ctx, MqttClientConfig config) { + return MqttClient.create(config, null, ctx.getExternalCallExecutor()); + } + + protected void prepareMqttClientConfig(MqttClientConfig config) { ClientCredentials credentials = this.mqttNodeConfiguration.getCredentials(); if (credentials.getType() == CredentialsType.BASIC) { BasicCredentials basicCredentials = (BasicCredentials) credentials; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java index b78a441134..cbf431d63a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java @@ -18,6 +18,7 @@ package org.thingsboard.rule.engine.mqtt.azure; import io.netty.handler.codec.mqtt.MqttVersion; import lombok.extern.slf4j.Slf4j; import org.thingsboard.common.util.AzureIotHubUtil; +import org.thingsboard.mqtt.MqttClient; import org.thingsboard.mqtt.MqttClientConfig; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; @@ -32,8 +33,6 @@ import org.thingsboard.rule.engine.mqtt.TbMqttNodeConfiguration; import org.thingsboard.server.common.data.plugin.ComponentClusteringMode; import org.thingsboard.server.common.data.plugin.ComponentType; -import javax.net.ssl.SSLException; - @Slf4j @RuleNode( type = ComponentType.EXTERNAL, @@ -60,13 +59,13 @@ public class TbAzureIotHubNode extends TbMqttNode { pemCredentials.setCaCert(AzureIotHubUtil.getDefaultCaCert()); } } - this.mqttClient = initClient(ctx); + this.mqttClient = initAzureClient(ctx); } catch (Exception e) { throw new TbNodeException(e); } } - protected void prepareMqttClientConfig(MqttClientConfig config) throws SSLException { + protected void prepareMqttClientConfig(MqttClientConfig config) { config.setProtocolVersion(MqttVersion.MQTT_3_1_1); config.setUsername(AzureIotHubUtil.buildUsername(mqttNodeConfiguration.getHost(), config.getClientId())); ClientCredentials credentials = mqttNodeConfiguration.getCredentials(); @@ -74,4 +73,8 @@ public class TbAzureIotHubNode extends TbMqttNode { config.setPassword(AzureIotHubUtil.buildSasToken(mqttNodeConfiguration.getHost(), ((AzureIotHubSasCredentials) credentials).getSasKey())); } } + + MqttClient initAzureClient(TbContext ctx) throws Exception { + return initClient(ctx); + } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java index 9db629a37c..c7b2d010a8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java @@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.rule.RuleNodeState; +import org.thingsboard.server.common.data.util.TbPair; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; @@ -52,6 +53,7 @@ import java.util.concurrent.TimeUnit; name = "device profile", customRelations = true, relationTypes = {"Alarm Created", "Alarm Updated", "Alarm Severity Updated", "Alarm Cleared", "Success", "Failure"}, + version = 1, configClazz = TbDeviceProfileNodeConfiguration.class, nodeDescription = "Process device messages based on device profile settings", nodeDetails = "Create and clear alarms based on alarm rules defined in device profile. The output relation type is either " + @@ -241,4 +243,25 @@ public class TbDeviceProfileNode implements TbNode { ctx.removeRuleNodeStateForEntity(deviceId); } } + + @Override + public TbPair upgrade(int fromVersion, JsonNode oldConfiguration) throws TbNodeException { + boolean hasChanges = false; + switch (fromVersion) { + case 0: + String persistAlarmRulesState = "persistAlarmRulesState"; + String fetchAlarmRulesStateOnStart = "fetchAlarmRulesStateOnStart"; + if (oldConfiguration.has(persistAlarmRulesState)) { + if (!oldConfiguration.get(persistAlarmRulesState).asBoolean()) { + hasChanges = true; + ((ObjectNode) oldConfiguration).put(fetchAlarmRulesStateOnStart, false); + } + } + break; + default: + break; + } + return new TbPair<>(hasChanges, oldConfiguration); + } + } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java index 52ce360bda..b15e0e8e3d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java @@ -51,6 +51,10 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; ) public class TbRabbitMqNode extends TbAbstractExternalNode { + private static final String supportedPropertiesStr = String.join(", ", + "BASIC", "TEXT_PLAIN", "MINIMAL_BASIC", "MINIMAL_PERSISTENT_BASIC", "PERSISTENT_BASIC", "PERSISTENT_TEXT_PLAIN" + ); + private static final Charset UTF8 = StandardCharsets.UTF_8; private static final String ERROR = "error"; @@ -64,16 +68,7 @@ public class TbRabbitMqNode extends TbAbstractExternalNode { public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { super.init(ctx); this.config = TbNodeUtils.convert(configuration, TbRabbitMqNodeConfiguration.class); - ConnectionFactory factory = new ConnectionFactory(); - factory.setHost(this.config.getHost()); - factory.setPort(this.config.getPort()); - factory.setVirtualHost(this.config.getVirtualHost()); - factory.setUsername(this.config.getUsername()); - factory.setPassword(this.config.getPassword()); - factory.setAutomaticRecoveryEnabled(this.config.isAutomaticRecoveryEnabled()); - factory.setConnectionTimeout(this.config.getConnectionTimeout()); - factory.setHandshakeTimeout(this.config.getHandshakeTimeout()); - this.config.getClientProperties().forEach((k,v) -> factory.getClientProperties().put(k,v)); + ConnectionFactory factory = getConnectionFactory(); try { this.connection = factory.newConnection(); this.channel = this.connection.createChannel(); @@ -90,6 +85,20 @@ public class TbRabbitMqNode extends TbAbstractExternalNode { t -> tellFailure(ctx, processException(tbMsg, t), t)); } + ConnectionFactory getConnectionFactory() { + ConnectionFactory factory = new ConnectionFactory(); + factory.setHost(this.config.getHost()); + factory.setPort(this.config.getPort()); + factory.setVirtualHost(this.config.getVirtualHost()); + factory.setUsername(this.config.getUsername()); + factory.setPassword(this.config.getPassword()); + factory.setAutomaticRecoveryEnabled(this.config.isAutomaticRecoveryEnabled()); + factory.setConnectionTimeout(this.config.getConnectionTimeout()); + factory.setHandshakeTimeout(this.config.getHandshakeTimeout()); + this.config.getClientProperties().forEach((k, v) -> factory.getClientProperties().put(k, v)); + return factory; + } + private ListenableFuture publishMessageAsync(TbContext ctx, TbMsg msg) { return ctx.getExternalCallExecutor().executeAsync(() -> publishMessage(ctx, msg)); } @@ -132,7 +141,7 @@ public class TbRabbitMqNode extends TbAbstractExternalNode { } } - private static AMQP.BasicProperties convert(String name) throws TbNodeException { + static AMQP.BasicProperties convert(String name) throws TbNodeException { switch (name) { case "BASIC": return MessageProperties.BASIC; @@ -147,7 +156,8 @@ public class TbRabbitMqNode extends TbAbstractExternalNode { case "PERSISTENT_TEXT_PLAIN": return MessageProperties.PERSISTENT_TEXT_PLAIN; default: - throw new TbNodeException("Message Properties: '" + name + "' is undefined!"); + throw new TbNodeException("Undefined message properties type '" + name + + "'! Only " + supportedPropertiesStr + " message properties types are supported!"); } } } 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 cc133632b9..2c723830bd 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -1,25 +1,25 @@ -System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/input","@angular/material/form-field","@angular/material/slide-toggle","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/button","@angular/material/icon","@angular/material/select","@angular/material/core","@angular/material/tooltip","@angular/material/expansion","rxjs","@shared/components/hint-tooltip-icon.component","@shared/components/help-popup.component","@shared/pipe/safe.pipe","@core/public-api","@shared/components/js-func.component","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/checkbox","@angular/material/chips","@shared/components/entity/entity-type-select.component","@shared/components/relation/relation-type-autocomplete.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","@shared/components/entity/entity-subtype-list.component","@home/components/relation/relation-filters.component","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,g,f,y,b,x,h,v,C,F,k,T,L,I,N,S,q,A,M,E,G,w,D,V,P,R,O,_,B,K,z,H,U,j,$,J,Q,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,ge,fe,ye,be,xe,he,ve,Ce,Fe,ke,Te,Le,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,we,De,Ve,Pe,Re,Oe,_e,Be,Ke,ze,He,Ue,je,$e,Je,Qe,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.InjectionToken,o=e.Injectable,a=e.Inject,i=e.Optional,l=e.EventEmitter,s=e.Directive,m=e.Input,p=e.Output,d=e.NgModule,u=e.ViewChild,c=e.forwardRef},function(e){g=e.RuleNodeConfigurationComponent,f=e.AttributeScope,y=e.telemetryTypeTranslations,b=e.ScriptLanguage,x=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.EntityType,F=e.entityFields,k=e.PageComponent,T=e.messageTypeNames,L=e.MessageType,I=e.coerceBoolean,N=e.entitySearchDirectionTranslations,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,w=e.NotificationType,D=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,H=e.FormGroup},function(e){U=e,j=e.DOCUMENT,$=e.CommonModule},function(e){J=e},function(e){Q=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e},function(e){oe=e},function(e){ae=e.Subject,ie=e.takeUntil,le=e.of,se=e.EMPTY,me=e.fromEvent},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e.getCurrentAuthState,ge=e,fe=e.isDefinedAndNotNull,ye=e.isEqual,be=e.deepTrim,xe=e.isObject,he=e.isNotEmptyStr},function(e){ve=e},function(e){Ce=e},function(e){Fe=e.ENTER,ke=e.COMMA,Te=e.SEMICOLON},function(e){Le=e},function(e){Ie=e},function(e){Ne=e},function(e){Se=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e},function(e){Ee=e.coerceBooleanProperty,Ge=e.coerceElement,we=e.coerceNumberProperty},function(e){De=e},function(e){Ve=e},function(e){Pe=e},function(e){Re=e},function(e){Oe=e.tap,_e=e.map,Be=e.startWith,Ke=e.mergeMap,ze=e.share,He=e.takeUntil,Ue=e.auditTime},function(e){je=e},function(e){$e=e},function(e){Je=e.HomeComponentsModule},function(e){Qe=e.__decorate},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
\n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});const ct=new r("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class gt{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new ae,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,deps:[{token:t.NgZone},{token:j},{token:ct,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),gt.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:a,args:[j]}]},{type:void 0,decorators:[{type:i},{type:a,args:[ct]}]}]}});class ft{constructor(e,t,n,r){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=r,this.cbOnSuccess=new l,this.cbOnError=new l,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:gt}],target:t.ɵɵFactoryTarget.Directive}),ft.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:ft,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,decorators:[{type:s,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:gt}]},propDecorators:{targetElm:[{type:m,args:["ngxClipboard"]}],container:[{type:m}],cbContent:[{type:m}],cbSuccessMsg:[{type:m}],cbOnSuccess:[{type:p}],cbOnError:[{type:p}]}});class yt{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,deps:[{token:gt},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),yt.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:yt,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,decorators:[{type:s,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:gt},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class bt{}bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,deps:[],target:t.ɵɵFactoryTarget.NgModule}),bt.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,declarations:[ft,yt],imports:[$],exports:[ft,yt]}),bt.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,decorators:[{type:d,args:[{imports:[$],declarations:[ft,yt],exports:[ft,yt]}]}]});class xt{constructor(){this.textAlign="left"}}e("ExampleHintComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:m}],popupHelpLink:[{type:m}],textAlign:[{type:m}]}});class ht extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===f.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vt extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.clearAlarmConfigForm}onConfigurationSet(e){this.clearAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===b.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===b.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",vt),vt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),vt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vt,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ct extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.alarmSeverities=Object.keys(x),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[Fe,ke,Te],this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.createAlarmConfigForm}onConfigurationSet(e){this.createAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==b.TBEL||this.tbelEnabled||(r=b.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===b.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===b.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",Ct),Ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ct,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ft extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.search-direction-from"],[v.TO,"tb.rulenode.search-direction-to"]]),this.entityType=C,this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]]})}validatorTriggers(){return["entityType","createEntityIfNotExists"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;if(t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==C.DEVICE&&t!==C.ASSET)this.createRelationConfigForm.get("entityTypePattern").setValidators([]);else{const e=[O.pattern(/.*\S.*/)];this.createRelationConfigForm.get("createEntityIfNotExists").value&&e.push(O.required),this.createRelationConfigForm.get("entityTypePattern").setValidators(e)}this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",Ft),Ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ft,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n\n
\n
tb.rulenode.target-entity
\n
\n \n \n\n \n {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n\n \n tb.rulenode.profile-name\n \n \n
\n\n \n\n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n\n
\n
tb.rulenode.target-entity
\n
\n \n \n\n \n {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n\n \n tb.rulenode.profile-name\n \n \n
\n\n \n\n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.del-relation-direction-from"],[v.TO,"tb.rulenode.del-relation-direction-to"]]),this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.entityType=C,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n&&n!==C.TENANT?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",kt),kt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n \n
\n
\n
\n \n \n \n {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n
\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n \n
\n
\n
\n \n \n \n {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n
\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.deviceProfile}onConfigurationSet(e){this.deviceProfile=this.fb.group({persistAlarmRulesState:[!!e&&e.persistAlarmRulesState,O.required],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart,O.required]})}}e("DeviceProfileConfigComponent",Tt),Tt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n',dependencies:[{kind:"component",type:Le.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:Tt,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 Lt extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}var It;e("GeneratorConfigComponent",Lt),Lt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Lt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lt,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:qe.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(It||(It={}));const Nt=new Map([[It.CUSTOMER,"tb.rulenode.originator-customer"],[It.TENANT,"tb.rulenode.originator-tenant"],[It.RELATED,"tb.rulenode.originator-related"],[It.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[It.ENTITY,"tb.rulenode.originator-entity"]]),St=new Map([[It.CUSTOMER,"tb.rulenode.originator-customer-desc"],[It.TENANT,"tb.rulenode.originator-tenant-desc"],[It.RELATED,"tb.rulenode.originator-related-entity-desc"],[It.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[It.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),qt=[F.createdTime,F.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},F.firstName,F.lastName,F.email,F.title,F.country,F.state,F.city,F.address,F.address2,F.zip,F.phone,F.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],At=new Map([["type","profileName"],["createdTime","createdTime"],["name","name"],["firstName","firstName"],["lastName","lastName"],["email","email"],["title","title"],["country","country"],["state","state"],["city","city"],["address","address"],["address2","address2"],["zip","zip"],["phone","phone"],["label","label"],["id","id"],["additionalInfo","additionalInfo"]]);var Mt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Mt||(Mt={}));const Et=new Map([[Mt.CIRCLE,"tb.rulenode.perimeter-circle"],[Mt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Gt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Gt||(Gt={}));const wt=new Map([[Gt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Gt.SECONDS,"tb.rulenode.time-unit-seconds"],[Gt.MINUTES,"tb.rulenode.time-unit-minutes"],[Gt.HOURS,"tb.rulenode.time-unit-hours"],[Gt.DAYS,"tb.rulenode.time-unit-days"]]);var Dt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(Dt||(Dt={}));const Vt=new Map([[Dt.METER,"tb.rulenode.range-unit-meter"],[Dt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[Dt.FOOT,"tb.rulenode.range-unit-foot"],[Dt.MILE,"tb.rulenode.range-unit-mile"],[Dt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Pt;!function(e){e.ID="ID",e.TITLE="TITLE",e.COUNTRY="COUNTRY",e.STATE="STATE",e.CITY="CITY",e.ZIP="ZIP",e.ADDRESS="ADDRESS",e.ADDRESS2="ADDRESS2",e.PHONE="PHONE",e.EMAIL="EMAIL",e.ADDITIONAL_INFO="ADDITIONAL_INFO"}(Pt||(Pt={}));const Rt=new Map([[Pt.ID,"tb.rulenode.entity-details-id"],[Pt.TITLE,"tb.rulenode.entity-details-title"],[Pt.COUNTRY,"tb.rulenode.entity-details-country"],[Pt.STATE,"tb.rulenode.entity-details-state"],[Pt.CITY,"tb.rulenode.entity-details-city"],[Pt.ZIP,"tb.rulenode.entity-details-zip"],[Pt.ADDRESS,"tb.rulenode.entity-details-address"],[Pt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Pt.PHONE,"tb.rulenode.entity-details-phone"],[Pt.EMAIL,"tb.rulenode.entity-details-email"],[Pt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Ot;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Ot||(Ot={}));const _t=new Map([[Ot.FIRST,"tb.rulenode.first"],[Ot.LAST,"tb.rulenode.last"],[Ot.ALL,"tb.rulenode.all"]]),Bt=new Map([[Ot.FIRST,"tb.rulenode.first-mode-hint"],[Ot.LAST,"tb.rulenode.last-mode-hint"],[Ot.ALL,"tb.rulenode.all-mode-hint"]]);var Kt,zt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Kt||(Kt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(zt||(zt={}));const Ht=new Map([[zt.ATTRIBUTES,"tb.rulenode.attributes"],[zt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[zt.FIELDS,"tb.rulenode.fields"]]),Ut=new Map([[zt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[zt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[zt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),jt=new Map([[Kt.ASC,"tb.rulenode.ascending"],[Kt.DESC,"tb.rulenode.descending"]]);var $t;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}($t||($t={}));const Jt=new Map([[$t.STANDARD,"tb.rulenode.sqs-queue-standard"],[$t.FIFO,"tb.rulenode.sqs-queue-fifo"]]),Qt=["anonymous","basic","cert.PEM"],Yt=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Wt=["sas","cert.PEM"],Zt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var Xt;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}(Xt||(Xt={}));const en=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],tn=new Map([["US-ASCII","tb.rulenode.charset-us-ascii"],["ISO-8859-1","tb.rulenode.charset-iso-8859-1"],["UTF-8","tb.rulenode.charset-utf-8"],["UTF-16BE","tb.rulenode.charset-utf-16be"],["UTF-16LE","tb.rulenode.charset-utf-16le"],["UTF-16","tb.rulenode.charset-utf-16"]]);var nn;!function(e){e.CUSTOM="CUSTOM",e.ADD="ADD",e.SUB="SUB",e.MULT="MULT",e.DIV="DIV",e.SIN="SIN",e.SINH="SINH",e.COS="COS",e.COSH="COSH",e.TAN="TAN",e.TANH="TANH",e.ACOS="ACOS",e.ASIN="ASIN",e.ATAN="ATAN",e.ATAN2="ATAN2",e.EXP="EXP",e.EXPM1="EXPM1",e.SQRT="SQRT",e.CBRT="CBRT",e.GET_EXP="GET_EXP",e.HYPOT="HYPOT",e.LOG="LOG",e.LOG10="LOG10",e.LOG1P="LOG1P",e.CEIL="CEIL",e.FLOOR="FLOOR",e.FLOOR_DIV="FLOOR_DIV",e.FLOOR_MOD="FLOOR_MOD",e.ABS="ABS",e.MIN="MIN",e.MAX="MAX",e.POW="POW",e.SIGNUM="SIGNUM",e.RAD="RAD",e.DEG="DEG"}(nn||(nn={}));const rn=new Map([[nn.CUSTOM,{value:nn.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[nn.ADD,{value:nn.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[nn.SUB,{value:nn.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[nn.MULT,{value:nn.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[nn.DIV,{value:nn.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[nn.SIN,{value:nn.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[nn.SINH,{value:nn.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[nn.COS,{value:nn.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[nn.COSH,{value:nn.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[nn.TAN,{value:nn.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[nn.TANH,{value:nn.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[nn.ACOS,{value:nn.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[nn.ASIN,{value:nn.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[nn.ATAN,{value:nn.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[nn.ATAN2,{value:nn.ATAN2,name:"2-argument arc tangent",description:"Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta)",minArgs:2,maxArgs:2}],[nn.EXP,{value:nn.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[nn.EXPM1,{value:nn.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[nn.SQRT,{value:nn.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[nn.CBRT,{value:nn.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[nn.GET_EXP,{value:nn.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[nn.HYPOT,{value:nn.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[nn.LOG,{value:nn.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[nn.LOG10,{value:nn.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[nn.LOG1P,{value:nn.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[nn.CEIL,{value:nn.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[nn.FLOOR,{value:nn.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[nn.FLOOR_DIV,{value:nn.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[nn.FLOOR_MOD,{value:nn.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[nn.ABS,{value:nn.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[nn.MIN,{value:nn.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[nn.MAX,{value:nn.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[nn.POW,{value:nn.POW,name:"Raise to a power",description:"Returns the value of the first argument raised to the power of the second argument",minArgs:2,maxArgs:2}],[nn.SIGNUM,{value:nn.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[nn.RAD,{value:nn.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[nn.DEG,{value:nn.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var on,an,ln;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(on||(on={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(an||(an={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(ln||(ln={}));const sn=new Map([[ln.DATA,"tb.rulenode.message-to-metadata"],[ln.METADATA,"tb.rulenode.metadata-to-message"]]),mn=(new Map([[ln.DATA,"tb.rulenode.from-message"],[ln.METADATA,"tb.rulenode.from-metadata"]]),new Map([[ln.DATA,"tb.rulenode.message"],[ln.METADATA,"tb.rulenode.metadata"]])),pn=new Map([[ln.DATA,"tb.rulenode.message"],[ln.METADATA,"tb.rulenode.message-metadata"]]),dn=new Map([[on.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[on.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[on.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[on.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[on.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),un=new Map([[an.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[an.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[an.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[an.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),cn=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var gn,fn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(gn||(gn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(fn||(fn={}));const yn=new Map([[gn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[gn.SERVER_SCOPE,"tb.rulenode.server-scope"],[gn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var bn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(bn||(bn={}));const xn=new Map([[bn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[bn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class hn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Mt,this.perimeterTypes=Object.keys(Mt),this.perimeterTypeTranslationMap=Et,this.rangeUnits=Object.keys(Dt),this.rangeUnitTranslationMap=Vt,this.presenceMonitoringStrategies=xn,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Gt),this.timeUnitsTranslationMap=wt,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[O.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Mt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Mt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n
\n
\n
{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
\n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
\n
{{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
\n
\n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n
\n
\n
{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
\n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
\n
{{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
\n
\n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vn extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-to-string-function"}configForm(){return this.logConfigForm}onConfigurationSet(e){this.logConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Cn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ln extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]],sessionIdMetaDataAttribute:[e?e.sessionIdMetaDataAttribute:null,[]],requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.session-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.session-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class In extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:c((()=>Nn)),multi:!0},{provide:K,useExisting:c((()=>Nn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:De.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ve.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:c((()=>Nn)),multi:!0},{provide:K,useExisting:c((()=>Nn)),multi:!0}],template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],required:[{type:m}]}});class Sn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class qn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.default-ttl\n \n \n help\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
\n \n tb.rulenode.default-ttl\n \n \n help\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class An extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[]],createCustomerIfNotExists:[!!e&&e?.createCustomerIfNotExists,[]]})}validatorTriggers(){return["createCustomerIfNotExists"]}updateValidators(e){this.unassignCustomerConfigForm.get("createCustomerIfNotExists").value?this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([]),this.unassignCustomerConfigForm.get("customerNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n
\n\n
\n
\n \n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n \n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
\n
\n\n
\n
\n \n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n \n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Mn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendRestApiCallReplyConfigForm}onConfigurationSet(e){this.sendRestApiCallReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]],serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]]})}}e("SendRestApiCallReplyConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-action-node-send-rest-api-call-reply-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-action-node-send-rest-api-call-reply-config",template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class En extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[Fe,ke,Te]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:u,args:["attributeChipList"]}]}});class Gn extends k{get function(){return this.functionValue}set function(e){e&&this.functionValue!==e&&(this.functionValue=e,this.setupArgumentsFormGroup(!0))}constructor(e,t){super(e),this.store=e,this.fb=t,this.maxArgs=16,this.minArgs=1,this.displayArgumentName=!1,this.mathFunctionMap=rn,this.ArgumentType=on,this.attributeScopeMap=yn,this.argumentTypeMap=dn,this.arguments=Object.values(on),this.attributeScope=Object.values(gn),this.propagateChange=null,this.valueChangeSubscription=[]}ngOnInit(){this.argumentsFormGroup=this.fb.group({arguments:this.fb.array([])}),this.valueChangeSubscription.push(this.argumentsFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))),this.setupArgumentsFormGroup()}onDrop(e){const t=this.argumentsFormArray,n=t.at(e.previousIndex);t.removeAt(e.previousIndex),t.insert(e.currentIndex,n),this.updateArgumentNames()}get argumentsFormArray(){return this.argumentsFormGroup.get("arguments")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.argumentsFormGroup.disable({emitEvent:!1}):(this.argumentsFormGroup.enable({emitEvent:!1}),this.argumentsFormArray.controls.forEach((e=>this.updateArgumentControlValidators(e))))}ngOnDestroy(){this.valueChangeSubscription.length&&this.valueChangeSubscription.forEach((e=>e.unsubscribe()))}writeValue(e){const t=[];e&&e.forEach(((e,n)=>{t.push(this.createArgumentControl(e,n))})),this.argumentsFormGroup.setControl("arguments",this.fb.array(t),{emitEvent:!1}),this.setupArgumentsFormGroup()}removeArgument(e){this.argumentsFormArray.removeAt(e),this.updateArgumentNames()}addArgument(e=!0){const t=this.argumentsFormArray,n=this.createArgumentControl(null,t.length);t.push(n,{emitEvent:e})}validate(e){return this.argumentsFormGroup.valid?null:{argumentsRequired:!0}}setupArgumentsFormGroup(e=!1){if(this.function&&(this.maxArgs=this.mathFunctionMap.get(this.function).maxArgs,this.minArgs=this.mathFunctionMap.get(this.function).minArgs,this.displayArgumentName=this.function===nn.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===on.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==on.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(cn[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:c((()=>Gn)),multi:!0},{provide:K,useExisting:c((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:U.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Pe.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Pe.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Re.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Re.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Re.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ve.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:c((()=>Gn)),multi:!0},{provide:K,useExisting:c((()=>Gn)),multi:!0}],template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],function:[{type:m}]}});class wn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.searchText="",this.dirty=!1,this.mathOperation=[...rn.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(Oe((e=>{let t;t="string"==typeof e&&nn[e]?nn[e]:null,this.updateView(t)})),_e((e=>(this.searchText=e||"",e?this._filter(e):this.mathOperation.slice()))))}_filter(e){const t=e.toLowerCase();return this.mathOperation.filter((e=>e.name.toLowerCase().includes(t)||e.value.toLowerCase().includes(t)))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.mathFunctionForm.disable({emitEvent:!1}):this.mathFunctionForm.enable({emitEvent:!1})}mathFunctionDisplayFn(e){if(e){const t=rn.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:c((()=>wn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:je.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:je.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:$e.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:c((()=>wn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:m}],disabled:[{type:m}],operationInput:[{type:u,args:["operationInput",{static:!0}]}]}});class Dn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=nn,this.ArgumentTypeResult=an,this.argumentTypeResultMap=un,this.attributeScopeMap=yn,this.argumentsResult=Object.values(an),this.attributeScopeResult=Object.values(fn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===nn.CUSTOM?(this.mathFunctionConfigForm.get("customFunction").enable({emitEvent:!1}),null===this.mathFunctionConfigForm.get("customFunction").value&&this.mathFunctionConfigForm.get("customFunction").patchValue("(x - 32) / 1.8",{emitEvent:!1})):this.mathFunctionConfigForm.get("customFunction").disable({emitEvent:!1}),n===an.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:wn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Vn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=T,this.eventOptions=[L.CONNECT_EVENT,L.ACTIVITY_EVENT,L.DISCONNECT_EVENT,L.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:fe(e?.event)?e.event:L.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[O.required]]})}}e("DeviceStateConfigComponent",Vn),Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'
\n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Pn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new ae,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof H){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ye(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Pn),Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:c((()=>Pn)),multi:!0},{provide:K,useExisting:c((()=>Pn)),multi:!0}],ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Pn.prototype,"disabled",void 0),Qe([I()],Pn.prototype,"uniqueKeyValuePairValidator",void 0),Qe([I()],Pn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:c((()=>Pn)),multi:!0},{provide:K,useExisting:c((()=>Pn)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class Rn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.entityType=C,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Rn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ye.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:c((()=>Rn)),multi:!0}],template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class On extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>On)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:We.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:c((()=>On)),multi:!0}],template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class _n extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.truncate=n,this.fb=r,this.placeholder="tb.rulenode.add-message-type",this.separatorKeysCodes=[Fe,ke,Te],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(L))this.messageTypesList.push({name:T.get(L[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Be(""),_e((e=>e||"")),Ke((e=>this.fetchMessageTypes(e))),ze())}setDisabledState(e){this.disabled=e,this.disabled?this.messageTypeConfigForm.disable({emitEvent:!1}):this.messageTypeConfigForm.enable({emitEvent:!1})}writeValue(e){this.searchText="",this.messageTypes.length=0,e&&e.forEach((e=>{const t=this.messageTypesList.find((t=>t.value===e));t?this.messageTypes.push({name:t.name,value:t.value}):this.messageTypes.push({name:e,value:e})}))}displayMessageTypeFn(e){return e?e.name:void 0}textIsNotEmpty(e){return e&&e.length>0}createMessageType(e,t){e.preventDefault(),this.transformMessageType(t)}add(e){this.transformMessageType(e.value)}fetchMessageTypes(e){if(this.searchText=e,this.searchText&&this.searchText.length){const e=this.searchText.toUpperCase();return le(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return le(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:c((()=>_n)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:je.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:je.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:je.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:$e.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:c((()=>_n)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:m}],label:[{type:m}],placeholder:[{type:m}],disabled:[{type:m}],chipList:[{type:u,args:["chipList",{static:!1}]}],matAutocomplete:[{type:u,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:u,args:["messageTypeInput",{static:!1}]}]}});class Bn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=Qt,this.credentialsTypeTranslationsMap=Yt,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){fe(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:c((()=>Bn)),multi:!0},{provide:K,useExisting:c((()=>Bn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:U.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:oe.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:oe.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:c((()=>Bn)),multi:!0},{provide:K,useExisting:c((()=>Bn)),multi:!0}],template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:m}],disableCertPemCredentials:[{type:m}],passwordFieldRequired:[{type:m}]}});class Kn{set required(e){this.requiredValue!==e&&(this.requiredValue=e,this.updateValidators())}get required(){return this.requiredValue}constructor(e){this.fb=e,this.subscriptSizing="fixed",this.messageTypes=[{name:"Post attributes",value:"POST_ATTRIBUTES_REQUEST"},{name:"Post telemetry",value:"POST_TELEMETRY_REQUEST"},{name:"Custom",value:""}],this.propagateChange=()=>{},this.destroy$=new ae,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(ie(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Kn)),multi:!0},{provide:K,useExisting:c((()=>Kn)),multi:!0}],ngImport:t,template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Kn.prototype,"disabled",void 0),Qe([I()],Kn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:c((()=>Kn)),multi:!0},{provide:K,useExisting:c((()=>Kn)),multi:!0}],template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:m}],disabled:[{type:m}],required:[{type:m}]}});class zn{constructor(e,t){this.fb=e,this.translate=t,this.translation=mn,this.propagateChange=()=>{},this.destroy$=new ae,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(He(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:c((()=>zn)),multi:!0}],ngImport:t,template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Ie.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Ie.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:c((()=>zn)),multi:!0}],template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:m}],translation:[{type:m}]}});class Hn extends k{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new ae,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof H){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ye(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(He(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)fe(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(He(this.destroy$)).subscribe((t=>{const n=At.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:c((()=>Hn)),multi:!0},{provide:K,useExisting:c((()=>Hn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Ve.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Hn.prototype,"disabled",void 0),Qe([I()],Hn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:c((()=>Hn)),multi:!0},{provide:K,useExisting:c((()=>Hn)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:m}],disabled:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],targetKeyPrefix:[{type:m}],selectText:[{type:m}],selectRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class Un extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:c((()=>Un)),multi:!0}],template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class jn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new ae,this.separatorKeysCodes=[Fe,ke,Te],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(He(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||fe(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:c((()=>jn)),multi:!0},{provide:K,useExisting:jn,multi:!0}],ngImport:t,template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:c((()=>jn)),multi:!0},{provide:K,useExisting:jn,multi:!0}],template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:m}]}});class $n extends k{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new ae,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(He(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:c((()=>$n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:Ie.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Ie.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:c((()=>$n)),multi:!0}],template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Jn{}e("RulenodeCoreConfigCommonModule",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Jn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Jn,declarations:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt],imports:[$,M,Je],exports:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt]}),Jn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,imports:[$,M,Je]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:d,args:[{declarations:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt],imports:[$,M,Je],exports:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt]}]}]});class Qn{}e("RuleNodeCoreConfigActionModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn],imports:[$,M,Je,Jn],exports:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[$,M,Je,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:d,args:[{declarations:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn],imports:[$,M,Je,Jn],exports:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn]}]}]});class Yn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[Fe,ke,Te]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]],excludeZeroDeltas:[e.excludeZeroDeltas,[]]})}prepareInputConfig(e){return{inputValueKey:fe(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:fe(e?.outputValueKey)?e.outputValueKey:null,useCache:!fe(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!fe(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:fe(e?.periodValueKey)?e.periodValueKey:null,round:fe(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!fe(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative,excludeZeroDeltas:!!fe(e?.excludeZeroDeltas)&&e.excludeZeroDeltas}}prepareOutputConfig(e){return be(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n \n
\n
\n
\n",dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n \n
\n
\n
\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Wn extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ht.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.customerAttributesConfigForm}prepareOutputConfig(e){const t={};for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,be(e)}prepareInputConfig(e){let t,n;return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Zn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return xe(e)&&(e.attributesControl={clientAttributeNames:fe(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:fe(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:fe(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!fe(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:fe(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!fe(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Rn,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:jn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Xn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Pt))this.predefinedValues.push({value:Pt[e],name:this.translate.instant(Rt.get(Pt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=fe(e?.addToMetadata)?e.addToMetadata?ln.METADATA:ln.DATA:e?.fetchTo?e.fetchTo:ln.DATA,{detailsList:fe(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class er extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[Fe,ke,Te],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Ot,this.samplingOrders=Object.values(Kt),this.samplingOrdersTranslate=jt,this.timeUnits=Object.values(Gt),this.timeUnitsTranslationMap=wt,this.deduplicationStrategiesHintTranslations=Bt,this.headerOptions=[],this.timeUnitMap={[Gt.MILLISECONDS]:1,[Gt.SECONDS]:1e3,[Gt.MINUTES]:6e4,[Gt.HOURS]:36e5,[Gt.DAYS]:864e5},this.intervalValidator=()=>e=>e.get("startInterval").value*this.timeUnitMap[e.get("startIntervalTimeUnit").value]<=e.get("endInterval").value*this.timeUnitMap[e.get("endIntervalTimeUnit").value]?{intervalError:!0}:null;for(const e of _t.keys())this.headerOptions.push({value:e,name:this.translate.instant(_t.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,be(e)}prepareInputConfig(e){return xe(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:fe(e?.aggregation)?e.aggregation:E.NONE,fetchMode:fe(e?.fetchMode)?e.fetchMode:Ot.FIRST,orderBy:fe(e?.orderBy)?e.orderBy:Kt.ASC,limit:fe(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!fe(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:fe(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:fe(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Gt.MINUTES,endInterval:fe(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:fe(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Gt.MINUTES},startIntervalPattern:fe(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:fe(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Ot.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Ot.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class tr extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.originatorAttributesConfigForm}onConfigurationSet(e){this.originatorAttributesConfigForm=this.fb.group({tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return xe(e)&&(e.attributesControl={clientAttributeNames:fe(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:fe(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:fe(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!fe(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA,tellFailureIfAbsent:!!fe(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:fe(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:jn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class nr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of qt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return be(e)}prepareInputConfig(e){return{dataMapping:fe(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:fe(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n',dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=zt,this.msgMetadataLabelTranslations=Ut,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(qt))this.originatorFields.push({value:qt[e].value,name:this.translate.instant(qt[e].name)});for(const e of Ht.keys())this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===zt.FIELDS?(e.dataMapping=e.svMap,delete e.svMap):(e.dataMapping=e.kvMap,delete e.kvMap);const t={};if(e&&e.dataMapping)for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,delete e.svMap,delete e.kvMap,be(e)}prepareInputConfig(e){let t,n,r={[F.name.value]:`relatedEntity${this.translate.instant(F.name.name)}`},o={serialNumber:"sn"};return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,t===zt.FIELDS?r=n:o=n,{relationsQuery:fe(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===zt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ht.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class ar extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class ir{}e("RulenodeCoreConfigEnrichmentModule",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[],target:t.ɵɵFactoryTarget.NgModule}),ir.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:ir,declarations:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar],imports:[$,M,Jn],exports:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar]}),ir.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:d,args:[{declarations:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar],imports:[$,M,Jn],exports:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar]}]}]});class lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Wt,this.azureIotHubCredentialsTypeTranslationsMap=Zt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:U.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:oe.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=en,this.ToByteStandartCharsetTypeTranslationMap=tn}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&he(e.clientId))},[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){he(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Bn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=w,this.entityType=C}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class dr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys(Xt)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("enableProxy").value,r=this.restApiCallConfigForm.get("useSystemProxyProperties").value;n&&!r?(this.restApiCallConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Bn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(D),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class br extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=$t,this.sqsQueueTypes=Object.keys($t),this.sqsQueueTypeTranslationsMap=Jt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.lambdaConfigForm}onConfigurationSet(e){this.lambdaConfigForm=this.fb.group({functionName:[e?e.functionName:null,[O.required]],qualifier:[e?e.qualifier:null,[]],accessKey:[e?e.accessKey:null,[O.required]],secretKey:[e?e.secretKey:null,[O.required]],region:[e?e.region:null,[O.required]],connectionTimeout:[e?e.connectionTimeout:null,[O.required,O.min(0)]],requestTimeout:[e?e.requestTimeout:null,[O.required,O.min(0)]],tellFailureIfFuncThrowsExc:[!!e&&e.tellFailureIfFuncThrowsExc,[]]})}}e("LambdaConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-external-node-lambda-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.function-configuration
\n
\n \n \n
\n \n {{\'tb.rulenode.function-name\' | translate}}\n \n \n {{\'tb.rulenode.function-name-required\' | translate}}\n \n \n \n {{\'tb.rulenode.qualifier\' | translate}}\n \n tb.rulenode.qualifier-hint\n \n
\n
\n\n
\n \n \n tb.rulenode.aws-credentials\n \n
\n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n tb.rulenode.connection-timeout\n \n \n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n \n help\n \n \n tb.rulenode.request-timeout\n \n \n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n \n help\n \n
\n
\n \n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-external-node-lambda-config",template:'
\n
\n
\n
tb.rulenode.function-configuration
\n
\n \n \n
\n \n {{\'tb.rulenode.function-name\' | translate}}\n \n \n {{\'tb.rulenode.function-name-required\' | translate}}\n \n \n \n {{\'tb.rulenode.qualifier\' | translate}}\n \n tb.rulenode.qualifier-hint\n \n
\n
\n\n
\n \n \n tb.rulenode.aws-credentials\n \n
\n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n tb.rulenode.connection-timeout\n \n \n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n \n help\n \n \n tb.rulenode.request-timeout\n \n \n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n \n help\n \n
\n
\n \n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vr{}e("RulenodeCoreConfigExternalModule",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),vr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:vr,declarations:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr],imports:[$,M,Je,Jn],exports:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr]}),vr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,imports:[$,M,Je,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:d,args:[{declarations:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr],imports:[$,M,Je,Jn],exports:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr]}]}]});class Cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:fe(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:$n,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:fe(e?.messageNames)?e.messageNames:[],metadataNames:fe(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!fe(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:fe(e?.messageNames)?e.messageNames:[],metadataNames:fe(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=N}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!fe(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:fe(e?.direction)?e.direction:null,entityType:fe(e?.entityType)?e.entityType:null,entityId:fe(e?.entityId)?e.entityId:null,relationType:fe(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Mt,this.perimeterTypes=Object.values(Mt),this.perimeterTypeTranslationMap=Et,this.rangeUnits=Object.values(Dt),this.rangeUnitTranslationMap=Vt,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:fe(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:fe(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:fe(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!fe(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:fe(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:fe(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:fe(e?.centerLongitude)?e.centerLongitude:null,range:fe(e?.range)?e.range:null,rangeUnit:fe(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:fe(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Mt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Mt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:fe(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:_n,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ir extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.RULE_CHAIN,C.RULE_NODE,C.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:fe(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:fe(e?.scriptLang)?e.scriptLang:b.JS,jsScript:fe(e?.jsScript)?e.jsScript:null,tbelScript:fe(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Sr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:fe(e?.scriptLang)?e.scriptLang:b.JS,jsScript:fe(e?.jsScript)?e.jsScript:null,tbelScript:fe(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class qr{}e("RuleNodeCoreConfigFilterModule",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),qr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:qr,declarations:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr],imports:[$,M,Jn],exports:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr]}),qr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:d,args:[{declarations:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr],imports:[$,M,Jn],exports:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr]}]}]});class Ar extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=It,this.originatorSources=Object.keys(It),this.originatorSourceTranslationMap=Nt,this.originatorSourceDescTranslationMap=St,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.USER,C.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===It.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===It.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Ar),Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ar,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Pe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Pe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:On,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Mr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-transformer-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Mr),Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,deps:[{token:P.Store},{token:R.FormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - const Er=mt({passive:!0});class Gr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return se;const t=Ge(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new ae,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Er),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Er)}}),r}stopMonitoring(e){const t=Ge(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Gr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class wr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new l}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:wr,deps:[{token:t.ElementRef},{token:Gr}],target:t.ɵɵFactoryTarget.Directive}),wr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:wr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:wr,decorators:[{type:s,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Gr}]},propDecorators:{cdkAutofill:[{type:p}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Dr{get minRows(){return this._minRows}set minRows(e){this._minRows=we(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=we(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Ee(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new ae,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();me(e,"resize").pipe(Ue(16),He(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Dr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Dr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:s,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:i},{type:a,args:[j]}]}]},propDecorators:{minRows:[{type:m,args:["cdkAutosizeMinRows"]}],maxRows:[{type:m,args:["cdkAutosizeMaxRows"]}],enabled:[{type:m,args:["cdkTextareaAutosize"]}],placeholder:[{type:m}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Vr{}Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Vr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,declarations:[wr,Dr],exports:[wr,Dr]}),Vr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,decorators:[{type:d,args:[{declarations:[wr,Dr],exports:[wr,Dr]}]}]});class Pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:fe(e?.fromTemplate)?e.fromTemplate:null,toTemplate:fe(e?.toTemplate)?e.toTemplate:null,ccTemplate:fe(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:fe(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:fe(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:fe(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:fe(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:fe(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Dr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Pe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Pe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=sn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.copyFrom?ln.METADATA:ln.DATA:fe(e?.copyFrom)?e.copyFrom:ln.DATA,{keys:fe(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=pn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.fromMetadata?ln.METADATA:ln.DATA:fe(e?.renameIn)?e?.renameIn:ln.DATA,{renameKeysMapping:fe(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class _r extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n",dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Br extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=mn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.fromMetadata?ln.METADATA:ln.DATA:fe(e?.deleteFrom)?e?.deleteFrom:ln.DATA,{keys:fe(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Br,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Ot,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=_t}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[fe(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[fe(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[fe(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[fe(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[fe(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Kn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class zr{}e("RulenodeCoreConfigTransformModule",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),zr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:zr,declarations:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr],imports:[$,M,Jn],exports:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr]}),zr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:d,args:[{declarations:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr],imports:[$,M,Jn],exports:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr]}]}]});class Hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=C}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({forwardMsgToDefaultRuleChain:[!!e&&e?.forwardMsgToDefaultRuleChain,[]],ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hr,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n \n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n \n
\n \n \n
\n
\n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
\n
\n
\n \n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n \n
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ur,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class jr{}e("RuleNodeCoreConfigFlowModule",jr),jr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),jr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:jr,declarations:[Hr,Ur],imports:[$,M,Jn],exports:[Hr,Ur]}),jr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,decorators:[{type:d,args:[{declarations:[Hr,Ur],imports:[$,M,Jn],exports:[Hr,Ur]}]}]});class $r{constructor(e){!function(e){e.setTranslation("en_US",{tb:{rulenode:{id:"Id","additional-info":"Additional Info","advanced-settings":"Advanced settings","create-entity-if-not-exists":"Create new entity if it doesn't exist","create-entity-if-not-exists-hint":"If enabled, a new entity with specified parameters will be created unless it already exists. Existing entities will be used as is for relation.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","device-name-pattern":"Device name","asset-name-pattern":"Asset name","entity-view-name-pattern":"Entity view name","customer-title-pattern":"Customer title","dashboard-name-pattern":"Dashboard title","user-name-pattern":"User email","edge-name-pattern":"Edge name","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","copy-message-type":"Copy message type","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","message-type-value":"Message type value","message-type-value-required":"Message type value is required","message-type-value-max-length":"Message type value should be less than 256","output-message-type":"Output message type","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer title","customer-name-pattern-required":"Customer title is required","customer-name-pattern-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","create-customer-if-not-exists":"Create new customer if it doesn't exist","unassign-from-customer":"Unassign from specific customer if originator is dashboard","unassign-from-customer-tooltip":"Only dashboards can be assigned to multiple customers at once. \nIf the message originator is a dashboard, you need to explicitly specify the customer's title to unassign from.","customer-cache-expiration":"Customers cache expiration time (sec)","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","interval-start":"Interval start","interval-end":"Interval end","time-unit":"Time unit","fetch-mode":"Fetch mode","order-by-timestamp":"Order by timestamp",limit:"Limit","limit-hint":"Min limit value is 2, max - 1000. If you want to fetch a single entry, select fetch mode 'First' or 'Last'.","limit-required":"Limit is required.","limit-range":"Limit should be in a range from 2 to 1000.","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Allowing range from 1 to 2147483647.","start-interval-value-required":"Interval start is required.","end-interval-value-required":"Interval end is required.",filter:"Filter",switch:"Switch","math-templatization-tooltip":"This field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","add-message-type":"Add message type","select-message-types-required":"At least one message type should be selected.","select-message-types":"Select message types","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one.","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","attributes-keys":"Attributes keys","attributes-keys-required":"Attributes keys are required","attributes-scope":"Attributes scope","attributes-scope-value":"Attributes scope value","attributes-scope-value-copy":"Copy attributes scope value","attributes-scope-hint":"Use the 'scope' metadata key to dynamically set the attribute scope per message. If provided, this overrides the scope set in the configuration.","notify-device":"Force notification to the device","send-attributes-updated-notification":"Send attributes updated notification","send-attributes-updated-notification-hint":"Send notification about updated attributes as a separate message to the rule engine queue.","send-attributes-deleted-notification":"Send attributes deleted notification","send-attributes-deleted-notification-hint":"Send notification about deleted attributes as a separate message to the rule engine queue.","update-attributes-only-on-value-change":"Save attributes only if the value changes","update-attributes-only-on-value-change-hint":"Updates the attributes on every incoming message disregarding if their value has changed. Increases API usage and reduces performance.","update-attributes-only-on-value-change-hint-enabled":"Updates the attributes only if their value has changed. If the value is not changed, no update to the attribute timestamp nor attribute change notification will be sent.","fetch-credentials-to-metadata":"Fetch credentials to metadata","notify-device-on-update-hint":"If enabled, force notification to the device about shared attributes update. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn off the notification, the message metadata must contain the 'notifyDevice' parameter set to 'false'. Any other case will trigger the notification to the device.","notify-device-on-delete-hint":"If enabled, force notification to the device about shared attributes removal. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn on the notification, the message metadata must contain the 'notifyDevice' parameter set to 'true'. In any other case, the notification will not be triggered to the device.","latest-timeseries":"Latest time series data keys","timeseries-keys":"Time series keys","timeseries-keys-required":"At least one time series key should be selected.","add-timeseries-key":"Add time series key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","relation-parameters":"Relation parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","default-ttl-hint":"Rule node will fetch Time-to-Live (TTL) value from the message metadata. If no value is present, it defaults to the TTL specified in the configuration. If the value is set to 0, the TTL from the tenant profile configuration will be applied.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","reply-routing-configuration":"Reply Routing Configuration","reply-routing-configuration-hint":"These configuration parameters specify the metadata key names used to identify the service and request for sending a reply back.","request-id-metadata-attribute":"Request Id","service-id-metadata-attribute":"Service Id","session-id-metadata-attribute":"Session Id","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-with-specific-entity":"Delete relation with specific entity","delete-relation-with-specific-entity-hint":"If enabled, will delete the relation with just one specific entity. Otherwise, the relation will be removed with all matching entities.","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output time series key prefix","output-timeseries-key-prefix-required":"Output time series key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","add-metadata-key-values-as-kafka-headers":"Add Message metadata key-value pairs to Kafka record headers","add-metadata-key-values-as-kafka-headers-hint":"If selected, key-value pairs from message metadata will be added to the outgoing records headers as byte arrays with predefined charset encoding.","charset-encoding":"Charset encoding","charset-encoding-required":"Charset encoding is required.","charset-us-ascii":"US-ASCII","charset-iso-8859-1":"ISO-8859-1","charset-utf-8":"UTF-8","charset-utf-16be":"UTF-16BE","charset-utf-16le":"UTF-16LE","charset-utf-16":"UTF-16","select-queue-hint":"The queue name can be selected from a drop-down list or add a custom name.","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","skip-latest-persistence-hint":"Rule node will not update values for incoming keys for the latest time series data. Useful for highly loaded use-cases to decrease the pressure on the DB.","use-server-ts":"Use server ts","use-server-ts-hint":"Rule node will use the timestamp of message processing instead of the timestamp from the message. Useful for all sorts of sequential processing if you merge messages from multiple sources (devices, assets, etc).","kv-map-pattern-hint":"All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","kv-map-single-pattern-hint":"Input field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","shared-scope":"Shared scope","server-scope":"Server scope","client-scope":"Client scope","attribute-type":"Attribute","constant-type":"Constant","time-series-type":"Time series","message-body-type":"Message","message-metadata-type":"Metadata","argument-tile":"Arguments","no-arguments-prompt":"No arguments configured","result-title":"Result","functions-field-input":"Functions","no-option-found":"No option found","argument-source-field-input":"Source","argument-source-field-input-required":"Argument source is required.","argument-key-field-input":"Key","argument-key-field-input-required":"Argument key is required.","constant-value-field-input":"Constant value","constant-value-field-input-required":"Constant value is required.","attribute-scope-field-input":"Attribute scope","attribute-scope-field-input-required":"Attribute scope os required.","default-value-field-input":"Default value","type-field-input":"Type","type-field-input-required":"Type is required.","key-field-input":"Key","add-entity-type":"Add entity type","add-device-profile":"Add device profile","key-field-input-required":"Key is required.","number-floating-point-field-input":"Number of digits after floating point","number-floating-point-field-input-hint":"Use 0 to convert result to integer","add-to-message-field-input":"Add to message","add-to-metadata-field-input":"Add to metadata","custom-expression-field-input":"Mathematical Expression","custom-expression-field-input-required":"Mathematical expression is required","custom-expression-field-input-hint":"Specify a mathematical expression to evaluate. Default expression demonstrates how to transform Fahrenheit to Celsius","retained-message":"Retained","attributes-mapping":"Attributes mapping","latest-telemetry-mapping":"Latest telemetry mapping","add-mapped-attribute-to":"Add mapped attributes to","add-mapped-latest-telemetry-to":"Add mapped latest telemetry to","add-mapped-fields-to":"Add mapped fields to","add-selected-details-to":"Add selected details to","clear-selected-types":"Clear selected types","clear-selected-details":"Clear selected details","clear-selected-fields":"Clear selected fields","clear-selected-keys":"Clear selected keys","geofence-configuration":"Geofence configuration","coordinate-field-names":"Coordinate field names","coordinate-field-hint":"Rule node tries to retrieve the specified fields from the message. If they are not present, it will look them up in the metadata.","presence-monitoring-strategy":"Presence monitoring strategy","presence-monitoring-strategy-on-first-message":"On first message","presence-monitoring-strategy-on-each-message":"On each message","presence-monitoring-strategy-on-first-message-hint":"Reports presence status 'Inside' or 'Outside' on the first message after the configured minimal duration has passed since previous presence status 'Entered' or 'Left' update.","presence-monitoring-strategy-on-each-message-hint":"Reports presence status 'Inside' or 'Outside' on each message after presence status 'Entered' or 'Left' update.","fetch-credentials-to":"Fetch credentials to","add-originator-attributes-to":"Add originator attributes to","originator-attributes":"Originator attributes","fetch-latest-telemetry-with-timestamp":"Fetch latest telemetry with timestamp","fetch-latest-telemetry-with-timestamp-tooltip":'If selected, latest telemetry values will be added to the outbound metadata with timestamp, e.g: "{{latestTsKeyName}}": "{"ts":1574329385897, "value":42}"',"tell-failure":"Tell failure if any of the attributes are missing","tell-failure-tooltip":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"created-time":"Created time","chip-help":"Press 'Enter' to complete {{inputName}} input. \nPress 'Backspace' to delete {{inputName}}. \nMultiple values supported.",detail:"detail","field-name":"field name","device-profile":"device profile","entity-type":"entity type","message-type":"message type","timeseries-key":"time series key",type:"Type","first-name":"First name","last-name":"Last name",label:"Label","originator-fields-mapping":"Originator fields mapping","add-mapped-originator-fields-to":"Add mapped originator fields to",fields:"Fields","skip-empty-fields":"Skip empty fields","skip-empty-fields-tooltip":"Fields with empty values will not be added to the output message/output metadata.","fetch-interval":"Fetch interval","fetch-strategy":"Fetch strategy","fetch-timeseries-from-to":"Fetch time series from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch time series invalid ("Interval start" should be less than "Interval end").',"use-metadata-dynamic-interval-tooltip":"If selected, the rule node will use dynamic interval start and end based on the message and metadata patterns.","all-mode-hint":'If selected fetch mode "All" rule node will retrieve telemetry from the fetch interval with configurable query parameters.',"first-mode-hint":'If selected fetch mode "First" rule node will retrieve the closest telemetry to the fetch interval\'s start.',"last-mode-hint":'If selected fetch mode "Last" rule node will retrieve the closest telemetry to the fetch interval\'s end.',ascending:"Ascending",descending:"Descending",min:"Min",max:"Max",average:"Average",sum:"Sum",count:"Count",none:"None","last-level-relation-tooltip":"If selected, the rule node will search related entities only on the level set in the max relation level.","last-level-device-relation-tooltip":"If selected, the rule node will search related devices only on the level set in the max relation level.","data-to-fetch":"Data to fetch","mapping-of-customers":"Mapping of customer's","map-fields-required":"All mapping fields are required.",attributes:"Attributes","related-device-attributes":"Related device attributes","add-selected-attributes-to":"Add selected attributes to","device-profiles":"Device profiles","mapping-of-tenant":"Mapping of tenant's","add-attribute-key":"Add attribute key","message-template":"Message template","message-template-required":"Message template is required","use-system-slack-settings":"Use system slack settings","slack-api-token":"Slack API token","slack-api-token-required":"Slack API token is required","keys-mapping":"keys mapping","add-key":"Add key",recipients:"Recipients","message-subject-and-content":"Message subject and content","template-rules-hint":"Both input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the message metadata.","originator-customer-desc":"Use customer of incoming message originator as new originator.","originator-tenant-desc":"Use current tenant as new originator.","originator-related-entity-desc":"Use related entity as new originator. Lookup based on configured relation type and direction.","originator-alarm-originator-desc":"Use alarm originator as new originator. Only if incoming message originator is alarm entity.","originator-entity-by-name-pattern-desc":"Use entity fetched from DB as new originator. Lookup based on entity type and specified name pattern.","email-from-template-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","recipients-block-main-hint":"Comma-separated address list. All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","forward-msg-default-rule-chain":"Forward message to the originator's default rule chain","forward-msg-default-rule-chain-tooltip":"If enabled, message will be forwarded to the originator's default rule chain, or rule chain from configuration, if originator has no default rule chain defined in the entity profile.","exclude-zero-deltas":"Exclude zero deltas from outbound message","exclude-zero-deltas-hint":'If enabled, the "{{outputValueKey}}" output key will be added to the outbound message if its value is not zero.',"exclude-zero-deltas-time-difference-hint":'If enabled, the "{{outputValueKey}}" and "{{periodValueKey}}" output keys will be added to the outbound message only if the "{{outputValueKey}}" value is not zero.',"search-direction-from":"From originator to target entity","search-direction-to":"From target entity to originator","del-relation-direction-from":"From originator","del-relation-direction-to":"To originator","target-entity":"Target entity","function-configuration":"Function configuration","function-name":"Function name","function-name-required":"Function name is required.",qualifier:"Qualifier","qualifier-hint":'If the qualifier is not specified, the default qualifier "$LATEST" will be used.',"aws-credentials":"AWS Credentials","connection-timeout":"Connection timeout","connection-timeout-required":"Connection timeout is required.","connection-timeout-min":"Min connection timeout is 0.","connection-timeout-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception.","request-timeout":"Request timeout","request-timeout-required":"Request timeout is required","request-timeout-min":"Min request timeout is 0","request-timeout-hint":"The amount of time to wait in seconds for the request to complete before giving up and timing out. A value of 0 means infinity, and is not recommended.","tell-failure-aws-lambda":"Tell Failure if AWS Lambda function execution raises exception","tell-failure-aws-lambda-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",$r),$r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),$r.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$r,declarations:[dt],imports:[$,M],exports:[Qn,qr,ir,vr,zr,jr,dt]}),$r.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,imports:[$,M,Qn,qr,ir,vr,zr,jr]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,decorators:[{type:d,args:[{declarations:[dt],imports:[$,M],exports:[Qn,qr,ir,vr,zr,jr,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map +System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/input","@angular/material/form-field","@angular/material/slide-toggle","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/button","@angular/material/icon","@angular/material/select","@angular/material/core","@angular/material/tooltip","@angular/material/expansion","rxjs","@shared/components/hint-tooltip-icon.component","@shared/components/help-popup.component","@shared/pipe/safe.pipe","@core/public-api","@shared/components/js-func.component","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/checkbox","@angular/material/chips","@shared/components/entity/entity-type-select.component","@shared/components/relation/relation-type-autocomplete.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","@shared/components/entity/entity-subtype-list.component","@home/components/relation/relation-filters.component","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,g,f,y,b,x,h,v,C,F,k,T,L,I,N,S,q,A,M,E,G,w,D,V,P,R,O,_,B,K,z,H,U,j,$,J,Q,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,ge,fe,ye,be,xe,he,ve,Ce,Fe,ke,Te,Le,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,we,De,Ve,Pe,Re,Oe,_e,Be,Ke,ze,He,Ue,je,$e,Je,Qe,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.InjectionToken,o=e.Injectable,a=e.Inject,i=e.Optional,l=e.EventEmitter,s=e.Directive,m=e.Input,p=e.Output,d=e.NgModule,u=e.ViewChild,c=e.forwardRef},function(e){g=e.RuleNodeConfigurationComponent,f=e.AttributeScope,y=e.telemetryTypeTranslations,b=e.ScriptLanguage,x=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.EntityType,F=e.entityFields,k=e.PageComponent,T=e.messageTypeNames,L=e.MessageType,I=e.coerceBoolean,N=e.entitySearchDirectionTranslations,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,w=e.NotificationType,D=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,H=e.FormGroup},function(e){U=e,j=e.DOCUMENT,$=e.CommonModule},function(e){J=e},function(e){Q=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e},function(e){oe=e},function(e){ae=e.Subject,ie=e.takeUntil,le=e.of,se=e.EMPTY,me=e.fromEvent},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e.getCurrentAuthState,ge=e,fe=e.isDefinedAndNotNull,ye=e.isEqual,be=e.deepTrim,xe=e.isObject,he=e.isNotEmptyStr},function(e){ve=e},function(e){Ce=e},function(e){Fe=e.ENTER,ke=e.COMMA,Te=e.SEMICOLON},function(e){Le=e},function(e){Ie=e},function(e){Ne=e},function(e){Se=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e},function(e){Ee=e.coerceBooleanProperty,Ge=e.coerceElement,we=e.coerceNumberProperty},function(e){De=e},function(e){Ve=e},function(e){Pe=e},function(e){Re=e},function(e){Oe=e.tap,_e=e.map,Be=e.startWith,Ke=e.mergeMap,ze=e.share,He=e.takeUntil,Ue=e.auditTime},function(e){je=e},function(e){$e=e},function(e){Je=e.HomeComponentsModule},function(e){Qe=e.__decorate},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
\n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});const ct=new r("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class gt{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new ae,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,deps:[{token:t.NgZone},{token:j},{token:ct,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),gt.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:a,args:[j]}]},{type:void 0,decorators:[{type:i},{type:a,args:[ct]}]}]}});class ft{constructor(e,t,n,r){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=r,this.cbOnSuccess=new l,this.cbOnError=new l,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:gt}],target:t.ɵɵFactoryTarget.Directive}),ft.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:ft,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,decorators:[{type:s,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:gt}]},propDecorators:{targetElm:[{type:m,args:["ngxClipboard"]}],container:[{type:m}],cbContent:[{type:m}],cbSuccessMsg:[{type:m}],cbOnSuccess:[{type:p}],cbOnError:[{type:p}]}});class yt{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,deps:[{token:gt},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),yt.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:yt,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,decorators:[{type:s,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:gt},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class bt{}bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,deps:[],target:t.ɵɵFactoryTarget.NgModule}),bt.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,declarations:[ft,yt],imports:[$],exports:[ft,yt]}),bt.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,decorators:[{type:d,args:[{imports:[$],declarations:[ft,yt],exports:[ft,yt]}]}]});class xt{constructor(){this.textAlign="left"}}e("ExampleHintComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:m}],popupHelpLink:[{type:m}],textAlign:[{type:m}]}});class ht extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===f.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vt extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.clearAlarmConfigForm}onConfigurationSet(e){this.clearAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===b.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===b.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",vt),vt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),vt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vt,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ct extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.alarmSeverities=Object.keys(x),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[Fe,ke,Te],this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.createAlarmConfigForm}onConfigurationSet(e){this.createAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==b.TBEL||this.tbelEnabled||(r=b.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===b.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===b.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",Ct),Ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ct,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ft extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.search-direction-from"],[v.TO,"tb.rulenode.search-direction-to"]]),this.entityType=C,this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]]})}validatorTriggers(){return["entityType","createEntityIfNotExists"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;if(t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==C.DEVICE&&t!==C.ASSET)this.createRelationConfigForm.get("entityTypePattern").setValidators([]);else{const e=[O.pattern(/.*\S.*/)];this.createRelationConfigForm.get("createEntityIfNotExists").value&&e.push(O.required),this.createRelationConfigForm.get("entityTypePattern").setValidators(e)}this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",Ft),Ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ft,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n\n
\n
tb.rulenode.target-entity
\n
\n \n \n\n \n {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n\n \n tb.rulenode.profile-name\n \n \n
\n\n \n\n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n\n
\n
tb.rulenode.target-entity
\n
\n \n \n\n \n {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n\n \n tb.rulenode.profile-name\n \n \n
\n\n \n\n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.del-relation-direction-from"],[v.TO,"tb.rulenode.del-relation-direction-to"]]),this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.entityType=C,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n&&n!==C.TENANT?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",kt),kt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n \n
\n
\n
\n \n \n \n {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n
\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n \n
\n
\n
\n \n \n \n {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n
\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.deviceProfile}onConfigurationSet(e){this.deviceProfile=this.fb.group({persistAlarmRulesState:[!!e&&e.persistAlarmRulesState],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart]})}validatorTriggers(){return["persistAlarmRulesState"]}updateValidators(e){this.deviceProfile.get("persistAlarmRulesState").value?this.deviceProfile.get("fetchAlarmRulesStateOnStart").enable({emitEvent:!1}):(this.deviceProfile.get("fetchAlarmRulesStateOnStart").setValue(!1,{emitEvent:!1}),this.deviceProfile.get("fetchAlarmRulesStateOnStart").disable({emitEvent:!1})),this.deviceProfile.get("fetchAlarmRulesStateOnStart").updateValueAndValidity({emitEvent:e})}}e("DeviceProfileConfigComponent",Tt),Tt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.device-profile-node-hint
\n
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n
\n',dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
\n
tb.rulenode.device-profile-node-hint
\n
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Lt extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}var It;e("GeneratorConfigComponent",Lt),Lt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Lt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lt,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:qe.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(It||(It={}));const Nt=new Map([[It.CUSTOMER,"tb.rulenode.originator-customer"],[It.TENANT,"tb.rulenode.originator-tenant"],[It.RELATED,"tb.rulenode.originator-related"],[It.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[It.ENTITY,"tb.rulenode.originator-entity"]]),St=new Map([[It.CUSTOMER,"tb.rulenode.originator-customer-desc"],[It.TENANT,"tb.rulenode.originator-tenant-desc"],[It.RELATED,"tb.rulenode.originator-related-entity-desc"],[It.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[It.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),qt=[F.createdTime,F.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},F.firstName,F.lastName,F.email,F.title,F.country,F.state,F.city,F.address,F.address2,F.zip,F.phone,F.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],At=new Map([["type","profileName"],["createdTime","createdTime"],["name","name"],["firstName","firstName"],["lastName","lastName"],["email","email"],["title","title"],["country","country"],["state","state"],["city","city"],["address","address"],["address2","address2"],["zip","zip"],["phone","phone"],["label","label"],["id","id"],["additionalInfo","additionalInfo"]]);var Mt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Mt||(Mt={}));const Et=new Map([[Mt.CIRCLE,"tb.rulenode.perimeter-circle"],[Mt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Gt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Gt||(Gt={}));const wt=new Map([[Gt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Gt.SECONDS,"tb.rulenode.time-unit-seconds"],[Gt.MINUTES,"tb.rulenode.time-unit-minutes"],[Gt.HOURS,"tb.rulenode.time-unit-hours"],[Gt.DAYS,"tb.rulenode.time-unit-days"]]);var Dt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(Dt||(Dt={}));const Vt=new Map([[Dt.METER,"tb.rulenode.range-unit-meter"],[Dt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[Dt.FOOT,"tb.rulenode.range-unit-foot"],[Dt.MILE,"tb.rulenode.range-unit-mile"],[Dt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Pt;!function(e){e.ID="ID",e.TITLE="TITLE",e.COUNTRY="COUNTRY",e.STATE="STATE",e.CITY="CITY",e.ZIP="ZIP",e.ADDRESS="ADDRESS",e.ADDRESS2="ADDRESS2",e.PHONE="PHONE",e.EMAIL="EMAIL",e.ADDITIONAL_INFO="ADDITIONAL_INFO"}(Pt||(Pt={}));const Rt=new Map([[Pt.ID,"tb.rulenode.entity-details-id"],[Pt.TITLE,"tb.rulenode.entity-details-title"],[Pt.COUNTRY,"tb.rulenode.entity-details-country"],[Pt.STATE,"tb.rulenode.entity-details-state"],[Pt.CITY,"tb.rulenode.entity-details-city"],[Pt.ZIP,"tb.rulenode.entity-details-zip"],[Pt.ADDRESS,"tb.rulenode.entity-details-address"],[Pt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Pt.PHONE,"tb.rulenode.entity-details-phone"],[Pt.EMAIL,"tb.rulenode.entity-details-email"],[Pt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Ot;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Ot||(Ot={}));const _t=new Map([[Ot.FIRST,"tb.rulenode.first"],[Ot.LAST,"tb.rulenode.last"],[Ot.ALL,"tb.rulenode.all"]]),Bt=new Map([[Ot.FIRST,"tb.rulenode.first-mode-hint"],[Ot.LAST,"tb.rulenode.last-mode-hint"],[Ot.ALL,"tb.rulenode.all-mode-hint"]]);var Kt,zt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Kt||(Kt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(zt||(zt={}));const Ht=new Map([[zt.ATTRIBUTES,"tb.rulenode.attributes"],[zt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[zt.FIELDS,"tb.rulenode.fields"]]),Ut=new Map([[zt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[zt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[zt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),jt=new Map([[Kt.ASC,"tb.rulenode.ascending"],[Kt.DESC,"tb.rulenode.descending"]]);var $t;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}($t||($t={}));const Jt=new Map([[$t.STANDARD,"tb.rulenode.sqs-queue-standard"],[$t.FIFO,"tb.rulenode.sqs-queue-fifo"]]),Qt=["anonymous","basic","cert.PEM"],Yt=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Wt=["sas","cert.PEM"],Zt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var Xt;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}(Xt||(Xt={}));const en=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],tn=new Map([["US-ASCII","tb.rulenode.charset-us-ascii"],["ISO-8859-1","tb.rulenode.charset-iso-8859-1"],["UTF-8","tb.rulenode.charset-utf-8"],["UTF-16BE","tb.rulenode.charset-utf-16be"],["UTF-16LE","tb.rulenode.charset-utf-16le"],["UTF-16","tb.rulenode.charset-utf-16"]]);var nn;!function(e){e.CUSTOM="CUSTOM",e.ADD="ADD",e.SUB="SUB",e.MULT="MULT",e.DIV="DIV",e.SIN="SIN",e.SINH="SINH",e.COS="COS",e.COSH="COSH",e.TAN="TAN",e.TANH="TANH",e.ACOS="ACOS",e.ASIN="ASIN",e.ATAN="ATAN",e.ATAN2="ATAN2",e.EXP="EXP",e.EXPM1="EXPM1",e.SQRT="SQRT",e.CBRT="CBRT",e.GET_EXP="GET_EXP",e.HYPOT="HYPOT",e.LOG="LOG",e.LOG10="LOG10",e.LOG1P="LOG1P",e.CEIL="CEIL",e.FLOOR="FLOOR",e.FLOOR_DIV="FLOOR_DIV",e.FLOOR_MOD="FLOOR_MOD",e.ABS="ABS",e.MIN="MIN",e.MAX="MAX",e.POW="POW",e.SIGNUM="SIGNUM",e.RAD="RAD",e.DEG="DEG"}(nn||(nn={}));const rn=new Map([[nn.CUSTOM,{value:nn.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[nn.ADD,{value:nn.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[nn.SUB,{value:nn.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[nn.MULT,{value:nn.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[nn.DIV,{value:nn.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[nn.SIN,{value:nn.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[nn.SINH,{value:nn.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[nn.COS,{value:nn.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[nn.COSH,{value:nn.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[nn.TAN,{value:nn.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[nn.TANH,{value:nn.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[nn.ACOS,{value:nn.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[nn.ASIN,{value:nn.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[nn.ATAN,{value:nn.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[nn.ATAN2,{value:nn.ATAN2,name:"2-argument arc tangent",description:"Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta)",minArgs:2,maxArgs:2}],[nn.EXP,{value:nn.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[nn.EXPM1,{value:nn.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[nn.SQRT,{value:nn.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[nn.CBRT,{value:nn.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[nn.GET_EXP,{value:nn.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[nn.HYPOT,{value:nn.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[nn.LOG,{value:nn.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[nn.LOG10,{value:nn.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[nn.LOG1P,{value:nn.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[nn.CEIL,{value:nn.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[nn.FLOOR,{value:nn.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[nn.FLOOR_DIV,{value:nn.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[nn.FLOOR_MOD,{value:nn.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[nn.ABS,{value:nn.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[nn.MIN,{value:nn.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[nn.MAX,{value:nn.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[nn.POW,{value:nn.POW,name:"Raise to a power",description:"Returns the value of the first argument raised to the power of the second argument",minArgs:2,maxArgs:2}],[nn.SIGNUM,{value:nn.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[nn.RAD,{value:nn.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[nn.DEG,{value:nn.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var on,an,ln;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(on||(on={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(an||(an={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(ln||(ln={}));const sn=new Map([[ln.DATA,"tb.rulenode.message-to-metadata"],[ln.METADATA,"tb.rulenode.metadata-to-message"]]),mn=(new Map([[ln.DATA,"tb.rulenode.from-message"],[ln.METADATA,"tb.rulenode.from-metadata"]]),new Map([[ln.DATA,"tb.rulenode.message"],[ln.METADATA,"tb.rulenode.metadata"]])),pn=new Map([[ln.DATA,"tb.rulenode.message"],[ln.METADATA,"tb.rulenode.message-metadata"]]),dn=new Map([[on.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[on.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[on.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[on.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[on.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),un=new Map([[an.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[an.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[an.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[an.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),cn=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var gn,fn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(gn||(gn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(fn||(fn={}));const yn=new Map([[gn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[gn.SERVER_SCOPE,"tb.rulenode.server-scope"],[gn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var bn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(bn||(bn={}));const xn=new Map([[bn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[bn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class hn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Mt,this.perimeterTypes=Object.keys(Mt),this.perimeterTypeTranslationMap=Et,this.rangeUnits=Object.keys(Dt),this.rangeUnitTranslationMap=Vt,this.presenceMonitoringStrategies=xn,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Gt),this.timeUnitsTranslationMap=wt,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[O.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Mt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Mt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n
\n
\n
{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
\n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
\n
{{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
\n
\n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n
\n
\n
{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
\n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
\n
{{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
\n
\n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vn extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-to-string-function"}configForm(){return this.logConfigForm}onConfigurationSet(e){this.logConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Cn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ln extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]],sessionIdMetaDataAttribute:[e?e.sessionIdMetaDataAttribute:null,[]],requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.session-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.session-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class In extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:c((()=>Nn)),multi:!0},{provide:K,useExisting:c((()=>Nn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:De.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ve.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:c((()=>Nn)),multi:!0},{provide:K,useExisting:c((()=>Nn)),multi:!0}],template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],required:[{type:m}]}});class Sn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class qn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.default-ttl\n \n \n help\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
\n \n tb.rulenode.default-ttl\n \n \n help\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class An extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[]],createCustomerIfNotExists:[!!e&&e?.createCustomerIfNotExists,[]]})}validatorTriggers(){return["createCustomerIfNotExists"]}updateValidators(e){this.unassignCustomerConfigForm.get("createCustomerIfNotExists").value?this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([]),this.unassignCustomerConfigForm.get("customerNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n
\n\n
\n
\n \n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n \n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
\n
\n\n
\n
\n \n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n \n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Mn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendRestApiCallReplyConfigForm}onConfigurationSet(e){this.sendRestApiCallReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]],serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]]})}}e("SendRestApiCallReplyConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-action-node-send-rest-api-call-reply-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-action-node-send-rest-api-call-reply-config",template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class En extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[Fe,ke,Te]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:u,args:["attributeChipList"]}]}});class Gn extends k{get function(){return this.functionValue}set function(e){e&&this.functionValue!==e&&(this.functionValue=e,this.setupArgumentsFormGroup(!0))}constructor(e,t){super(e),this.store=e,this.fb=t,this.maxArgs=16,this.minArgs=1,this.displayArgumentName=!1,this.mathFunctionMap=rn,this.ArgumentType=on,this.attributeScopeMap=yn,this.argumentTypeMap=dn,this.arguments=Object.values(on),this.attributeScope=Object.values(gn),this.propagateChange=null,this.valueChangeSubscription=[]}ngOnInit(){this.argumentsFormGroup=this.fb.group({arguments:this.fb.array([])}),this.valueChangeSubscription.push(this.argumentsFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))),this.setupArgumentsFormGroup()}onDrop(e){const t=this.argumentsFormArray,n=t.at(e.previousIndex);t.removeAt(e.previousIndex),t.insert(e.currentIndex,n),this.updateArgumentNames()}get argumentsFormArray(){return this.argumentsFormGroup.get("arguments")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.argumentsFormGroup.disable({emitEvent:!1}):(this.argumentsFormGroup.enable({emitEvent:!1}),this.argumentsFormArray.controls.forEach((e=>this.updateArgumentControlValidators(e))))}ngOnDestroy(){this.valueChangeSubscription.length&&this.valueChangeSubscription.forEach((e=>e.unsubscribe()))}writeValue(e){const t=[];e&&e.forEach(((e,n)=>{t.push(this.createArgumentControl(e,n))})),this.argumentsFormGroup.setControl("arguments",this.fb.array(t),{emitEvent:!1}),this.setupArgumentsFormGroup()}removeArgument(e){this.argumentsFormArray.removeAt(e),this.updateArgumentNames()}addArgument(e=!0){const t=this.argumentsFormArray,n=this.createArgumentControl(null,t.length);t.push(n,{emitEvent:e})}validate(e){return this.argumentsFormGroup.valid?null:{argumentsRequired:!0}}setupArgumentsFormGroup(e=!1){if(this.function&&(this.maxArgs=this.mathFunctionMap.get(this.function).maxArgs,this.minArgs=this.mathFunctionMap.get(this.function).minArgs,this.displayArgumentName=this.function===nn.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===on.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==on.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(cn[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:c((()=>Gn)),multi:!0},{provide:K,useExisting:c((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:U.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Pe.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Pe.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Re.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Re.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Re.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ve.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:c((()=>Gn)),multi:!0},{provide:K,useExisting:c((()=>Gn)),multi:!0}],template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],function:[{type:m}]}});class wn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.searchText="",this.dirty=!1,this.mathOperation=[...rn.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(Oe((e=>{let t;t="string"==typeof e&&nn[e]?nn[e]:null,this.updateView(t)})),_e((e=>(this.searchText=e||"",e?this._filter(e):this.mathOperation.slice()))))}_filter(e){const t=e.toLowerCase();return this.mathOperation.filter((e=>e.name.toLowerCase().includes(t)||e.value.toLowerCase().includes(t)))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.mathFunctionForm.disable({emitEvent:!1}):this.mathFunctionForm.enable({emitEvent:!1})}mathFunctionDisplayFn(e){if(e){const t=rn.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:c((()=>wn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:je.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:je.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:$e.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:c((()=>wn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:m}],disabled:[{type:m}],operationInput:[{type:u,args:["operationInput",{static:!0}]}]}});class Dn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=nn,this.ArgumentTypeResult=an,this.argumentTypeResultMap=un,this.attributeScopeMap=yn,this.argumentsResult=Object.values(an),this.attributeScopeResult=Object.values(fn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===nn.CUSTOM?(this.mathFunctionConfigForm.get("customFunction").enable({emitEvent:!1}),null===this.mathFunctionConfigForm.get("customFunction").value&&this.mathFunctionConfigForm.get("customFunction").patchValue("(x - 32) / 1.8",{emitEvent:!1})):this.mathFunctionConfigForm.get("customFunction").disable({emitEvent:!1}),n===an.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:wn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Vn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=T,this.eventOptions=[L.CONNECT_EVENT,L.ACTIVITY_EVENT,L.DISCONNECT_EVENT,L.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:fe(e?.event)?e.event:L.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[O.required]]})}}e("DeviceStateConfigComponent",Vn),Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'
\n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Pn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new ae,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof H){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ye(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Pn),Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:c((()=>Pn)),multi:!0},{provide:K,useExisting:c((()=>Pn)),multi:!0}],ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Pn.prototype,"disabled",void 0),Qe([I()],Pn.prototype,"uniqueKeyValuePairValidator",void 0),Qe([I()],Pn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:c((()=>Pn)),multi:!0},{provide:K,useExisting:c((()=>Pn)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class Rn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.entityType=C,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Rn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ye.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:c((()=>Rn)),multi:!0}],template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class On extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>On)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:We.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:c((()=>On)),multi:!0}],template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class _n extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.truncate=n,this.fb=r,this.placeholder="tb.rulenode.add-message-type",this.separatorKeysCodes=[Fe,ke,Te],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(L))this.messageTypesList.push({name:T.get(L[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Be(""),_e((e=>e||"")),Ke((e=>this.fetchMessageTypes(e))),ze())}setDisabledState(e){this.disabled=e,this.disabled?this.messageTypeConfigForm.disable({emitEvent:!1}):this.messageTypeConfigForm.enable({emitEvent:!1})}writeValue(e){this.searchText="",this.messageTypes.length=0,e&&e.forEach((e=>{const t=this.messageTypesList.find((t=>t.value===e));t?this.messageTypes.push({name:t.name,value:t.value}):this.messageTypes.push({name:e,value:e})}))}displayMessageTypeFn(e){return e?e.name:void 0}textIsNotEmpty(e){return e&&e.length>0}createMessageType(e,t){e.preventDefault(),this.transformMessageType(t)}add(e){this.transformMessageType(e.value)}fetchMessageTypes(e){if(this.searchText=e,this.searchText&&this.searchText.length){const e=this.searchText.toUpperCase();return le(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return le(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:c((()=>_n)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:je.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:je.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:je.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:$e.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:c((()=>_n)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:m}],label:[{type:m}],placeholder:[{type:m}],disabled:[{type:m}],chipList:[{type:u,args:["chipList",{static:!1}]}],matAutocomplete:[{type:u,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:u,args:["messageTypeInput",{static:!1}]}]}});class Bn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=Qt,this.credentialsTypeTranslationsMap=Yt,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){fe(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:c((()=>Bn)),multi:!0},{provide:K,useExisting:c((()=>Bn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:U.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:oe.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:oe.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:c((()=>Bn)),multi:!0},{provide:K,useExisting:c((()=>Bn)),multi:!0}],template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:m}],disableCertPemCredentials:[{type:m}],passwordFieldRequired:[{type:m}]}});class Kn{set required(e){this.requiredValue!==e&&(this.requiredValue=e,this.updateValidators())}get required(){return this.requiredValue}constructor(e){this.fb=e,this.subscriptSizing="fixed",this.messageTypes=[{name:"Post attributes",value:"POST_ATTRIBUTES_REQUEST"},{name:"Post telemetry",value:"POST_TELEMETRY_REQUEST"},{name:"Custom",value:""}],this.propagateChange=()=>{},this.destroy$=new ae,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(ie(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Kn)),multi:!0},{provide:K,useExisting:c((()=>Kn)),multi:!0}],ngImport:t,template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Kn.prototype,"disabled",void 0),Qe([I()],Kn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:c((()=>Kn)),multi:!0},{provide:K,useExisting:c((()=>Kn)),multi:!0}],template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:m}],disabled:[{type:m}],required:[{type:m}]}});class zn{constructor(e,t){this.fb=e,this.translate=t,this.translation=mn,this.propagateChange=()=>{},this.destroy$=new ae,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(He(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:c((()=>zn)),multi:!0}],ngImport:t,template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Ie.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Ie.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:c((()=>zn)),multi:!0}],template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:m}],translation:[{type:m}]}});class Hn extends k{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new ae,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof H){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ye(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(He(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)fe(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(He(this.destroy$)).subscribe((t=>{const n=At.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:c((()=>Hn)),multi:!0},{provide:K,useExisting:c((()=>Hn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Ve.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Hn.prototype,"disabled",void 0),Qe([I()],Hn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:c((()=>Hn)),multi:!0},{provide:K,useExisting:c((()=>Hn)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:m}],disabled:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],targetKeyPrefix:[{type:m}],selectText:[{type:m}],selectRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class Un extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:c((()=>Un)),multi:!0}],template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class jn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new ae,this.separatorKeysCodes=[Fe,ke,Te],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(He(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||fe(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:c((()=>jn)),multi:!0},{provide:K,useExisting:jn,multi:!0}],ngImport:t,template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:c((()=>jn)),multi:!0},{provide:K,useExisting:jn,multi:!0}],template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:m}]}});class $n extends k{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new ae,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(He(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:c((()=>$n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:Ie.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Ie.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:c((()=>$n)),multi:!0}],template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Jn{}e("RulenodeCoreConfigCommonModule",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Jn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Jn,declarations:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt],imports:[$,M,Je],exports:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt]}),Jn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,imports:[$,M,Je]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:d,args:[{declarations:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt],imports:[$,M,Je],exports:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt]}]}]});class Qn{}e("RuleNodeCoreConfigActionModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn],imports:[$,M,Je,Jn],exports:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[$,M,Je,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:d,args:[{declarations:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn],imports:[$,M,Je,Jn],exports:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn]}]}]});class Yn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[Fe,ke,Te]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]],excludeZeroDeltas:[e.excludeZeroDeltas,[]]})}prepareInputConfig(e){return{inputValueKey:fe(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:fe(e?.outputValueKey)?e.outputValueKey:null,useCache:!fe(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!fe(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:fe(e?.periodValueKey)?e.periodValueKey:null,round:fe(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!fe(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative,excludeZeroDeltas:!!fe(e?.excludeZeroDeltas)&&e.excludeZeroDeltas}}prepareOutputConfig(e){return be(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n \n
\n
\n
\n",dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n \n
\n
\n
\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Wn extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ht.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.customerAttributesConfigForm}prepareOutputConfig(e){const t={};for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,be(e)}prepareInputConfig(e){let t,n;return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Zn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return xe(e)&&(e.attributesControl={clientAttributeNames:fe(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:fe(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:fe(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!fe(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:fe(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!fe(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Rn,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:jn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Xn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Pt))this.predefinedValues.push({value:Pt[e],name:this.translate.instant(Rt.get(Pt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=fe(e?.addToMetadata)?e.addToMetadata?ln.METADATA:ln.DATA:e?.fetchTo?e.fetchTo:ln.DATA,{detailsList:fe(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class er extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[Fe,ke,Te],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Ot,this.samplingOrders=Object.values(Kt),this.samplingOrdersTranslate=jt,this.timeUnits=Object.values(Gt),this.timeUnitsTranslationMap=wt,this.deduplicationStrategiesHintTranslations=Bt,this.headerOptions=[],this.timeUnitMap={[Gt.MILLISECONDS]:1,[Gt.SECONDS]:1e3,[Gt.MINUTES]:6e4,[Gt.HOURS]:36e5,[Gt.DAYS]:864e5},this.intervalValidator=()=>e=>e.get("startInterval").value*this.timeUnitMap[e.get("startIntervalTimeUnit").value]<=e.get("endInterval").value*this.timeUnitMap[e.get("endIntervalTimeUnit").value]?{intervalError:!0}:null;for(const e of _t.keys())this.headerOptions.push({value:e,name:this.translate.instant(_t.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,be(e)}prepareInputConfig(e){return xe(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:fe(e?.aggregation)?e.aggregation:E.NONE,fetchMode:fe(e?.fetchMode)?e.fetchMode:Ot.FIRST,orderBy:fe(e?.orderBy)?e.orderBy:Kt.ASC,limit:fe(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!fe(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:fe(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:fe(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Gt.MINUTES,endInterval:fe(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:fe(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Gt.MINUTES},startIntervalPattern:fe(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:fe(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Ot.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Ot.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class tr extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.originatorAttributesConfigForm}onConfigurationSet(e){this.originatorAttributesConfigForm=this.fb.group({tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return xe(e)&&(e.attributesControl={clientAttributeNames:fe(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:fe(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:fe(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!fe(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA,tellFailureIfAbsent:!!fe(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:fe(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:jn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class nr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of qt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return be(e)}prepareInputConfig(e){return{dataMapping:fe(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:fe(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n',dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=zt,this.msgMetadataLabelTranslations=Ut,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(qt))this.originatorFields.push({value:qt[e].value,name:this.translate.instant(qt[e].name)});for(const e of Ht.keys())this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===zt.FIELDS?(e.dataMapping=e.svMap,delete e.svMap):(e.dataMapping=e.kvMap,delete e.kvMap);const t={};if(e&&e.dataMapping)for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,delete e.svMap,delete e.kvMap,be(e)}prepareInputConfig(e){let t,n,r={[F.name.value]:`relatedEntity${this.translate.instant(F.name.name)}`},o={serialNumber:"sn"};return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,t===zt.FIELDS?r=n:o=n,{relationsQuery:fe(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===zt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ht.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class ar extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class ir{}e("RulenodeCoreConfigEnrichmentModule",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[],target:t.ɵɵFactoryTarget.NgModule}),ir.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:ir,declarations:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar],imports:[$,M,Jn],exports:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar]}),ir.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:d,args:[{declarations:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar],imports:[$,M,Jn],exports:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar]}]}]});class lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Wt,this.azureIotHubCredentialsTypeTranslationsMap=Zt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:U.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:oe.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=en,this.ToByteStandartCharsetTypeTranslationMap=tn}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&he(e.clientId))},[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){he(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Bn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=w,this.entityType=C}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class dr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys(Xt)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("enableProxy").value,r=this.restApiCallConfigForm.get("useSystemProxyProperties").value;n&&!r?(this.restApiCallConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Bn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(D),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class br extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=$t,this.sqsQueueTypes=Object.keys($t),this.sqsQueueTypeTranslationsMap=Jt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.lambdaConfigForm}onConfigurationSet(e){this.lambdaConfigForm=this.fb.group({functionName:[e?e.functionName:null,[O.required]],qualifier:[e?e.qualifier:null,[]],accessKey:[e?e.accessKey:null,[O.required]],secretKey:[e?e.secretKey:null,[O.required]],region:[e?e.region:null,[O.required]],connectionTimeout:[e?e.connectionTimeout:null,[O.required,O.min(0)]],requestTimeout:[e?e.requestTimeout:null,[O.required,O.min(0)]],tellFailureIfFuncThrowsExc:[!!e&&e.tellFailureIfFuncThrowsExc,[]]})}}e("LambdaConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-external-node-lambda-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.function-configuration
\n
\n \n \n
\n \n {{\'tb.rulenode.function-name\' | translate}}\n \n \n {{\'tb.rulenode.function-name-required\' | translate}}\n \n \n \n {{\'tb.rulenode.qualifier\' | translate}}\n \n tb.rulenode.qualifier-hint\n \n
\n
\n\n
\n \n \n tb.rulenode.aws-credentials\n \n
\n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n tb.rulenode.connection-timeout\n \n \n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n \n help\n \n \n tb.rulenode.request-timeout\n \n \n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n \n help\n \n
\n
\n \n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-external-node-lambda-config",template:'
\n
\n
\n
tb.rulenode.function-configuration
\n
\n \n \n
\n \n {{\'tb.rulenode.function-name\' | translate}}\n \n \n {{\'tb.rulenode.function-name-required\' | translate}}\n \n \n \n {{\'tb.rulenode.qualifier\' | translate}}\n \n tb.rulenode.qualifier-hint\n \n
\n
\n\n
\n \n \n tb.rulenode.aws-credentials\n \n
\n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n tb.rulenode.connection-timeout\n \n \n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n \n help\n \n \n tb.rulenode.request-timeout\n \n \n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n \n help\n \n
\n
\n \n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vr{}e("RulenodeCoreConfigExternalModule",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),vr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:vr,declarations:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr],imports:[$,M,Je,Jn],exports:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr]}),vr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,imports:[$,M,Je,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:d,args:[{declarations:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr],imports:[$,M,Je,Jn],exports:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr]}]}]});class Cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:fe(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:$n,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:fe(e?.messageNames)?e.messageNames:[],metadataNames:fe(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!fe(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:fe(e?.messageNames)?e.messageNames:[],metadataNames:fe(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=N}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!fe(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:fe(e?.direction)?e.direction:null,entityType:fe(e?.entityType)?e.entityType:null,entityId:fe(e?.entityId)?e.entityId:null,relationType:fe(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Mt,this.perimeterTypes=Object.values(Mt),this.perimeterTypeTranslationMap=Et,this.rangeUnits=Object.values(Dt),this.rangeUnitTranslationMap=Vt,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:fe(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:fe(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:fe(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!fe(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:fe(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:fe(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:fe(e?.centerLongitude)?e.centerLongitude:null,range:fe(e?.range)?e.range:null,rangeUnit:fe(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:fe(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Mt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Mt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:fe(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:_n,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ir extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.RULE_CHAIN,C.RULE_NODE,C.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:fe(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:fe(e?.scriptLang)?e.scriptLang:b.JS,jsScript:fe(e?.jsScript)?e.jsScript:null,tbelScript:fe(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Sr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:fe(e?.scriptLang)?e.scriptLang:b.JS,jsScript:fe(e?.jsScript)?e.jsScript:null,tbelScript:fe(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class qr{}e("RuleNodeCoreConfigFilterModule",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),qr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:qr,declarations:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr],imports:[$,M,Jn],exports:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr]}),qr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:d,args:[{declarations:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr],imports:[$,M,Jn],exports:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr]}]}]});class Ar extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=It,this.originatorSources=Object.keys(It),this.originatorSourceTranslationMap=Nt,this.originatorSourceDescTranslationMap=St,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.USER,C.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===It.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===It.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Ar),Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ar,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Pe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Pe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:On,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Mr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-transformer-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Mr),Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,deps:[{token:P.Store},{token:R.FormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + const Er=mt({passive:!0});class Gr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return se;const t=Ge(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new ae,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Er),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Er)}}),r}stopMonitoring(e){const t=Ge(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Gr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class wr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new l}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:wr,deps:[{token:t.ElementRef},{token:Gr}],target:t.ɵɵFactoryTarget.Directive}),wr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:wr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:wr,decorators:[{type:s,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Gr}]},propDecorators:{cdkAutofill:[{type:p}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Dr{get minRows(){return this._minRows}set minRows(e){this._minRows=we(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=we(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Ee(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new ae,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();me(e,"resize").pipe(Ue(16),He(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Dr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Dr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:s,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:i},{type:a,args:[j]}]}]},propDecorators:{minRows:[{type:m,args:["cdkAutosizeMinRows"]}],maxRows:[{type:m,args:["cdkAutosizeMaxRows"]}],enabled:[{type:m,args:["cdkTextareaAutosize"]}],placeholder:[{type:m}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Vr{}Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Vr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,declarations:[wr,Dr],exports:[wr,Dr]}),Vr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,decorators:[{type:d,args:[{declarations:[wr,Dr],exports:[wr,Dr]}]}]});class Pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:fe(e?.fromTemplate)?e.fromTemplate:null,toTemplate:fe(e?.toTemplate)?e.toTemplate:null,ccTemplate:fe(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:fe(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:fe(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:fe(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:fe(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:fe(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Dr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Pe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Pe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=sn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.copyFrom?ln.METADATA:ln.DATA:fe(e?.copyFrom)?e.copyFrom:ln.DATA,{keys:fe(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=pn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.fromMetadata?ln.METADATA:ln.DATA:fe(e?.renameIn)?e?.renameIn:ln.DATA,{renameKeysMapping:fe(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class _r extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n",dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Br extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=mn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.fromMetadata?ln.METADATA:ln.DATA:fe(e?.deleteFrom)?e?.deleteFrom:ln.DATA,{keys:fe(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Br,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Ot,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=_t}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[fe(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[fe(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[fe(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[fe(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[fe(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Kn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class zr{}e("RulenodeCoreConfigTransformModule",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),zr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:zr,declarations:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr],imports:[$,M,Jn],exports:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr]}),zr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:d,args:[{declarations:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr],imports:[$,M,Jn],exports:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr]}]}]});class Hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=C}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({forwardMsgToDefaultRuleChain:[!!e&&e?.forwardMsgToDefaultRuleChain,[]],ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hr,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n \n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n \n
\n \n \n
\n
\n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
\n
\n
\n \n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n \n
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ur,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class jr{}e("RuleNodeCoreConfigFlowModule",jr),jr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),jr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:jr,declarations:[Hr,Ur],imports:[$,M,Jn],exports:[Hr,Ur]}),jr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,decorators:[{type:d,args:[{declarations:[Hr,Ur],imports:[$,M,Jn],exports:[Hr,Ur]}]}]});class $r{constructor(e){!function(e){e.setTranslation("en_US",{tb:{rulenode:{id:"Id","additional-info":"Additional Info","advanced-settings":"Advanced settings","create-entity-if-not-exists":"Create new entity if it doesn't exist","create-entity-if-not-exists-hint":"If enabled, a new entity with specified parameters will be created unless it already exists. Existing entities will be used as is for relation.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","device-name-pattern":"Device name","asset-name-pattern":"Asset name","entity-view-name-pattern":"Entity view name","customer-title-pattern":"Customer title","dashboard-name-pattern":"Dashboard title","user-name-pattern":"User email","edge-name-pattern":"Edge name","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","copy-message-type":"Copy message type","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","message-type-value":"Message type value","message-type-value-required":"Message type value is required","message-type-value-max-length":"Message type value should be less than 256","output-message-type":"Output message type","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer title","customer-name-pattern-required":"Customer title is required","customer-name-pattern-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","create-customer-if-not-exists":"Create new customer if it doesn't exist","unassign-from-customer":"Unassign from specific customer if originator is dashboard","unassign-from-customer-tooltip":"Only dashboards can be assigned to multiple customers at once. \nIf the message originator is a dashboard, you need to explicitly specify the customer's title to unassign from.","customer-cache-expiration":"Customers cache expiration time (sec)","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","interval-start":"Interval start","interval-end":"Interval end","time-unit":"Time unit","fetch-mode":"Fetch mode","order-by-timestamp":"Order by timestamp",limit:"Limit","limit-hint":"Min limit value is 2, max - 1000. If you want to fetch a single entry, select fetch mode 'First' or 'Last'.","limit-required":"Limit is required.","limit-range":"Limit should be in a range from 2 to 1000.","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Allowing range from 1 to 2147483647.","start-interval-value-required":"Interval start is required.","end-interval-value-required":"Interval end is required.",filter:"Filter",switch:"Switch","math-templatization-tooltip":"This field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","add-message-type":"Add message type","select-message-types-required":"At least one message type should be selected.","select-message-types":"Select message types","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one.","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","attributes-keys":"Attributes keys","attributes-keys-required":"Attributes keys are required","attributes-scope":"Attributes scope","attributes-scope-value":"Attributes scope value","attributes-scope-value-copy":"Copy attributes scope value","attributes-scope-hint":"Use the 'scope' metadata key to dynamically set the attribute scope per message. If provided, this overrides the scope set in the configuration.","notify-device":"Force notification to the device","send-attributes-updated-notification":"Send attributes updated notification","send-attributes-updated-notification-hint":"Send notification about updated attributes as a separate message to the rule engine queue.","send-attributes-deleted-notification":"Send attributes deleted notification","send-attributes-deleted-notification-hint":"Send notification about deleted attributes as a separate message to the rule engine queue.","update-attributes-only-on-value-change":"Save attributes only if the value changes","update-attributes-only-on-value-change-hint":"Updates the attributes on every incoming message disregarding if their value has changed. Increases API usage and reduces performance.","update-attributes-only-on-value-change-hint-enabled":"Updates the attributes only if their value has changed. If the value is not changed, no update to the attribute timestamp nor attribute change notification will be sent.","fetch-credentials-to-metadata":"Fetch credentials to metadata","notify-device-on-update-hint":"If enabled, force notification to the device about shared attributes update. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn off the notification, the message metadata must contain the 'notifyDevice' parameter set to 'false'. Any other case will trigger the notification to the device.","notify-device-on-delete-hint":"If enabled, force notification to the device about shared attributes removal. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn on the notification, the message metadata must contain the 'notifyDevice' parameter set to 'true'. In any other case, the notification will not be triggered to the device.","latest-timeseries":"Latest time series data keys","timeseries-keys":"Time series keys","timeseries-keys-required":"At least one time series key should be selected.","add-timeseries-key":"Add time series key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","relation-parameters":"Relation parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","default-ttl-hint":"Rule node will fetch Time-to-Live (TTL) value from the message metadata. If no value is present, it defaults to the TTL specified in the configuration. If the value is set to 0, the TTL from the tenant profile configuration will be applied.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","reply-routing-configuration":"Reply Routing Configuration","reply-routing-configuration-hint":"These configuration parameters specify the metadata key names used to identify the service and request for sending a reply back.","request-id-metadata-attribute":"Request Id","service-id-metadata-attribute":"Service Id","session-id-metadata-attribute":"Session Id","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-with-specific-entity":"Delete relation with specific entity","delete-relation-with-specific-entity-hint":"If enabled, will delete the relation with just one specific entity. Otherwise, the relation will be removed with all matching entities.","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output time series key prefix","output-timeseries-key-prefix-required":"Output time series key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","add-metadata-key-values-as-kafka-headers":"Add Message metadata key-value pairs to Kafka record headers","add-metadata-key-values-as-kafka-headers-hint":"If selected, key-value pairs from message metadata will be added to the outgoing records headers as byte arrays with predefined charset encoding.","charset-encoding":"Charset encoding","charset-encoding-required":"Charset encoding is required.","charset-us-ascii":"US-ASCII","charset-iso-8859-1":"ISO-8859-1","charset-utf-8":"UTF-8","charset-utf-16be":"UTF-16BE","charset-utf-16le":"UTF-16LE","charset-utf-16":"UTF-16","select-queue-hint":"The queue name can be selected from a drop-down list or add a custom name.","device-profile-node-hint":"Useful if you have duration or repeating conditions to ensure continuity of alarm state evaluation.","persist-alarm-rules":"Persist state of alarm rules","persist-alarm-rules-hint":"If enabled, the rule node will store the state of processing to the database.","fetch-alarm-rules":"Fetch state of alarm rules","fetch-alarm-rules-hint":"If enabled, the rule node will restore the state of processing on initialization and ensure that alarms are raised even after server restarts. Otherwise, the state will be restored when the first message from the device arrives.","input-value-key":"Input value key","input-value-key-required":"Input value key is required.","output-value-key":"Output value key","output-value-key-required":"Output value key is required.","number-of-digits-after-floating-point":"Number of digits after floating point","number-of-digits-after-floating-point-range":"Number of digits after floating point should be in a range from 0 to 15.","failure-if-delta-negative":"Tell Failure if delta is negative","failure-if-delta-negative-tooltip":"Rule node forces failure of message processing if delta value is negative.","use-caching":"Use caching","use-caching-tooltip":'Rule node will cache the value of "{{inputValueKey}}" that arrives from the incoming message to improve performance. Note that the cache will not be updated if you modify the "{{inputValueKey}}" value elsewhere.',"add-time-difference-between-readings":'Add the time difference between "{{inputValueKey}}" readings',"add-time-difference-between-readings-tooltip":'If enabled, the rule node will add the "{{periodValueKey}}" to the outbound message.',"period-value-key":"Period value key","period-value-key-required":"Period value key is required.","general-pattern-hint":"Use ${metadataKey} for value from metadata, $[messageKey] for value from message body.","alarm-severity-pattern-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body. Alarm severity should be system (CRITICAL, MAJOR etc.)',"output-node-name-hint":"The rule node name corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain.","skip-latest-persistence":"Skip latest persistence","skip-latest-persistence-hint":"Rule node will not update values for incoming keys for the latest time series data. Useful for highly loaded use-cases to decrease the pressure on the DB.","use-server-ts":"Use server ts","use-server-ts-hint":"Rule node will use the timestamp of message processing instead of the timestamp from the message. Useful for all sorts of sequential processing if you merge messages from multiple sources (devices, assets, etc).","kv-map-pattern-hint":"All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","kv-map-single-pattern-hint":"Input field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","shared-scope":"Shared scope","server-scope":"Server scope","client-scope":"Client scope","attribute-type":"Attribute","constant-type":"Constant","time-series-type":"Time series","message-body-type":"Message","message-metadata-type":"Metadata","argument-tile":"Arguments","no-arguments-prompt":"No arguments configured","result-title":"Result","functions-field-input":"Functions","no-option-found":"No option found","argument-source-field-input":"Source","argument-source-field-input-required":"Argument source is required.","argument-key-field-input":"Key","argument-key-field-input-required":"Argument key is required.","constant-value-field-input":"Constant value","constant-value-field-input-required":"Constant value is required.","attribute-scope-field-input":"Attribute scope","attribute-scope-field-input-required":"Attribute scope os required.","default-value-field-input":"Default value","type-field-input":"Type","type-field-input-required":"Type is required.","key-field-input":"Key","add-entity-type":"Add entity type","add-device-profile":"Add device profile","key-field-input-required":"Key is required.","number-floating-point-field-input":"Number of digits after floating point","number-floating-point-field-input-hint":"Use 0 to convert result to integer","add-to-message-field-input":"Add to message","add-to-metadata-field-input":"Add to metadata","custom-expression-field-input":"Mathematical Expression","custom-expression-field-input-required":"Mathematical expression is required","custom-expression-field-input-hint":"Specify a mathematical expression to evaluate. Default expression demonstrates how to transform Fahrenheit to Celsius","retained-message":"Retained","attributes-mapping":"Attributes mapping","latest-telemetry-mapping":"Latest telemetry mapping","add-mapped-attribute-to":"Add mapped attributes to","add-mapped-latest-telemetry-to":"Add mapped latest telemetry to","add-mapped-fields-to":"Add mapped fields to","add-selected-details-to":"Add selected details to","clear-selected-types":"Clear selected types","clear-selected-details":"Clear selected details","clear-selected-fields":"Clear selected fields","clear-selected-keys":"Clear selected keys","geofence-configuration":"Geofence configuration","coordinate-field-names":"Coordinate field names","coordinate-field-hint":"Rule node tries to retrieve the specified fields from the message. If they are not present, it will look them up in the metadata.","presence-monitoring-strategy":"Presence monitoring strategy","presence-monitoring-strategy-on-first-message":"On first message","presence-monitoring-strategy-on-each-message":"On each message","presence-monitoring-strategy-on-first-message-hint":"Reports presence status 'Inside' or 'Outside' on the first message after the configured minimal duration has passed since previous presence status 'Entered' or 'Left' update.","presence-monitoring-strategy-on-each-message-hint":"Reports presence status 'Inside' or 'Outside' on each message after presence status 'Entered' or 'Left' update.","fetch-credentials-to":"Fetch credentials to","add-originator-attributes-to":"Add originator attributes to","originator-attributes":"Originator attributes","fetch-latest-telemetry-with-timestamp":"Fetch latest telemetry with timestamp","fetch-latest-telemetry-with-timestamp-tooltip":'If selected, latest telemetry values will be added to the outbound metadata with timestamp, e.g: "{{latestTsKeyName}}": "{"ts":1574329385897, "value":42}"',"tell-failure":"Tell failure if any of the attributes are missing","tell-failure-tooltip":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"created-time":"Created time","chip-help":"Press 'Enter' to complete {{inputName}} input. \nPress 'Backspace' to delete {{inputName}}. \nMultiple values supported.",detail:"detail","field-name":"field name","device-profile":"device profile","entity-type":"entity type","message-type":"message type","timeseries-key":"time series key",type:"Type","first-name":"First name","last-name":"Last name",label:"Label","originator-fields-mapping":"Originator fields mapping","add-mapped-originator-fields-to":"Add mapped originator fields to",fields:"Fields","skip-empty-fields":"Skip empty fields","skip-empty-fields-tooltip":"Fields with empty values will not be added to the output message/output metadata.","fetch-interval":"Fetch interval","fetch-strategy":"Fetch strategy","fetch-timeseries-from-to":"Fetch time series from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch time series invalid ("Interval start" should be less than "Interval end").',"use-metadata-dynamic-interval-tooltip":"If selected, the rule node will use dynamic interval start and end based on the message and metadata patterns.","all-mode-hint":'If selected fetch mode "All" rule node will retrieve telemetry from the fetch interval with configurable query parameters.',"first-mode-hint":'If selected fetch mode "First" rule node will retrieve the closest telemetry to the fetch interval\'s start.',"last-mode-hint":'If selected fetch mode "Last" rule node will retrieve the closest telemetry to the fetch interval\'s end.',ascending:"Ascending",descending:"Descending",min:"Min",max:"Max",average:"Average",sum:"Sum",count:"Count",none:"None","last-level-relation-tooltip":"If selected, the rule node will search related entities only on the level set in the max relation level.","last-level-device-relation-tooltip":"If selected, the rule node will search related devices only on the level set in the max relation level.","data-to-fetch":"Data to fetch","mapping-of-customers":"Mapping of customer's","map-fields-required":"All mapping fields are required.",attributes:"Attributes","related-device-attributes":"Related device attributes","add-selected-attributes-to":"Add selected attributes to","device-profiles":"Device profiles","mapping-of-tenant":"Mapping of tenant's","add-attribute-key":"Add attribute key","message-template":"Message template","message-template-required":"Message template is required","use-system-slack-settings":"Use system slack settings","slack-api-token":"Slack API token","slack-api-token-required":"Slack API token is required","keys-mapping":"keys mapping","add-key":"Add key",recipients:"Recipients","message-subject-and-content":"Message subject and content","template-rules-hint":"Both input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the message metadata.","originator-customer-desc":"Use customer of incoming message originator as new originator.","originator-tenant-desc":"Use current tenant as new originator.","originator-related-entity-desc":"Use related entity as new originator. Lookup based on configured relation type and direction.","originator-alarm-originator-desc":"Use alarm originator as new originator. Only if incoming message originator is alarm entity.","originator-entity-by-name-pattern-desc":"Use entity fetched from DB as new originator. Lookup based on entity type and specified name pattern.","email-from-template-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","recipients-block-main-hint":"Comma-separated address list. All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","forward-msg-default-rule-chain":"Forward message to the originator's default rule chain","forward-msg-default-rule-chain-tooltip":"If enabled, message will be forwarded to the originator's default rule chain, or rule chain from configuration, if originator has no default rule chain defined in the entity profile.","exclude-zero-deltas":"Exclude zero deltas from outbound message","exclude-zero-deltas-hint":'If enabled, the "{{outputValueKey}}" output key will be added to the outbound message if its value is not zero.',"exclude-zero-deltas-time-difference-hint":'If enabled, the "{{outputValueKey}}" and "{{periodValueKey}}" output keys will be added to the outbound message only if the "{{outputValueKey}}" value is not zero.',"search-direction-from":"From originator to target entity","search-direction-to":"From target entity to originator","del-relation-direction-from":"From originator","del-relation-direction-to":"To originator","target-entity":"Target entity","function-configuration":"Function configuration","function-name":"Function name","function-name-required":"Function name is required.",qualifier:"Qualifier","qualifier-hint":'If the qualifier is not specified, the default qualifier "$LATEST" will be used.',"aws-credentials":"AWS Credentials","connection-timeout":"Connection timeout","connection-timeout-required":"Connection timeout is required.","connection-timeout-min":"Min connection timeout is 0.","connection-timeout-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception.","request-timeout":"Request timeout","request-timeout-required":"Request timeout is required","request-timeout-min":"Min request timeout is 0","request-timeout-hint":"The amount of time to wait in seconds for the request to complete before giving up and timing out. A value of 0 means infinity, and is not recommended.","tell-failure-aws-lambda":"Tell Failure if AWS Lambda function execution raises exception","tell-failure-aws-lambda-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",$r),$r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),$r.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$r,declarations:[dt],imports:[$,M],exports:[Qn,qr,ir,vr,zr,jr,dt]}),$r.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,imports:[$,M,Qn,qr,ir,vr,zr,jr]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,decorators:[{type:d,args:[{declarations:[dt],imports:[$,M],exports:[Qn,qr,ir,vr,zr,jr,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNodeTest.java new file mode 100644 index 0000000000..309023b3c6 --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNodeTest.java @@ -0,0 +1,255 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.gcp.pubsub; + +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.cloud.pubsub.v1.Publisher; +import com.google.protobuf.ByteString; +import com.google.pubsub.v1.PubsubMessage; +import org.junit.jupiter.api.BeforeEach; +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.MethodSource; +import org.mockito.ArgumentCaptor; +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.common.util.ListeningExecutor; +import org.thingsboard.rule.engine.TestDbCallbackExecutor; +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.api.util.TbNodeUtils; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.data.msg.TbNodeConnectionType; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; + +import java.io.IOException; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; +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.given; +import static org.mockito.BDDMockito.never; +import static org.mockito.BDDMockito.spy; +import static org.mockito.BDDMockito.then; +import static org.mockito.BDDMockito.willReturn; +import static org.mockito.BDDMockito.willThrow; + +@ExtendWith(MockitoExtension.class) +class TbPubSubNodeTest { + + private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("d29849c2-3f21-48e2-8557-74cdd6403290")); + private final ListeningExecutor executor = new TestDbCallbackExecutor(); + + private TbPubSubNode node; + private TbPubSubNodeConfiguration config; + + @Mock + private Publisher pubSubClientMock; + @Mock + private TbContext ctxMock; + + @BeforeEach + public void setUp() throws IOException { + node = spy(new TbPubSubNode()); + config = new TbPubSubNodeConfiguration().defaultConfiguration(); + } + + @Test + public void verifyDefaultConfig() { + assertThat(config.getProjectId()).isEqualTo("my-google-cloud-project-id"); + assertThat(config.getTopicName()).isEqualTo("my-pubsub-topic-name"); + assertThat(config.getMessageAttributes()).isEmpty(); + assertThat(config.getServiceAccountKey()).isNull(); + assertThat(config.getServiceAccountKeyFileName()).isNull(); + } + + @Test + public void givenValidConfig_whenInit_thenOk() throws IOException { + willReturn(pubSubClientMock).given(node).initPubSubClient(ctxMock); + + assertThatNoException().isThrownBy(() -> node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))); + } + + @Test + public void givenErrorOccursDuringInitClient_whenInit_thenThrowsException() throws IOException { + willThrow(new RuntimeException("Could not initialize client!")).given(node).initPubSubClient(ctxMock); + + assertThatThrownBy(() -> node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) + .isInstanceOf(TbNodeException.class).hasMessage("java.lang.RuntimeException: Could not initialize client!"); + } + + @ParameterizedTest + @MethodSource + public void givenForceAckIsTrueAndMessageAttributesPatterns_whenOnMsg_thenEnqueueForTellNext( + String attributeName, String attributeValue, TbMsgMetaData metaData, String data) throws IOException, TbNodeException { + config.setMessageAttributes(Map.of(attributeName, attributeValue)); + given(ctxMock.isExternalNodeForceAck()).willReturn(true); + willReturn(pubSubClientMock).given(node).initPubSubClient(ctxMock); + + String messageId = "2070443601311540"; + given(pubSubClientMock.publish(any())).willReturn(ApiFutures.immediateFuture(messageId)); + given(ctxMock.getExternalCallExecutor()).willReturn(executor); + + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, data); + node.onMsg(ctxMock, msg); + + then(ctxMock).should().ack(msg); + PubsubMessage.Builder pubsubMessageBuilder = PubsubMessage.newBuilder(); + pubsubMessageBuilder.setData(ByteString.copyFromUtf8(msg.getData())); + this.config.getMessageAttributes().forEach((k, v) -> { + String name = TbNodeUtils.processPattern(k, msg); + String val = TbNodeUtils.processPattern(v, msg); + pubsubMessageBuilder.putAttributes(name, val); + }); + then(pubSubClientMock).should().publish(pubsubMessageBuilder.build()); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + then(ctxMock).should().enqueueForTellNext(actualMsg.capture(), eq(TbNodeConnectionType.SUCCESS)); + metaData.putValue("messageId", messageId); + TbMsg expectedMsg = TbMsg.transformMsgMetadata(msg, metaData); + assertThat(actualMsg.getValue()) + .usingRecursiveComparison() + .ignoringFields("ctx") + .isEqualTo(expectedMsg); + } + + private static Stream givenForceAckIsTrueAndMessageAttributesPatterns_whenOnMsg_thenEnqueueForTellNext() { + return Stream.of( + Arguments.of("attributeName", "attributeValue", new TbMsgMetaData(), TbMsg.EMPTY_JSON_OBJECT), + Arguments.of("${mdAttrName}", "${mdAttrValue}", new TbMsgMetaData( + Map.of( + "mdAttrName", "mdAttributeName", + "mdAttrValue", "mdAttributeValue" + )), TbMsg.EMPTY_JSON_OBJECT), + Arguments.of("$[msgAttrName]", "$[msgAttrValue]", new TbMsgMetaData(), + "{\"msgAttrName\": \"msgAttributeName\", \"msgAttrValue\": \"mdAttributeValue\"}") + ); + } + + @Test + public void givenForceAckIsFalse_whenOnMsg_thenTellSuccess() throws IOException, TbNodeException { + given(ctxMock.isExternalNodeForceAck()).willReturn(false); + willReturn(pubSubClientMock).given(node).initPubSubClient(ctxMock); + + String messageId = "2070443601311540"; + given(pubSubClientMock.publish(any())).willReturn(ApiFutures.immediateFuture(messageId)); + given(ctxMock.getExternalCallExecutor()).willReturn(executor); + + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsgMetaData metadata = new TbMsgMetaData(); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metadata, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + then(ctxMock).should(never()).ack(msg); + PubsubMessage.Builder pubsubMessageBuilder = PubsubMessage.newBuilder(); + pubsubMessageBuilder.setData(ByteString.copyFromUtf8(msg.getData())); + then(pubSubClientMock).should().publish(pubsubMessageBuilder.build()); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + then(ctxMock).should().tellSuccess(actualMsg.capture()); + metadata.putValue("messageId", messageId); + TbMsg expectedMsg = TbMsg.transformMsgMetadata(msg, metadata); + assertThat(actualMsg.getValue()) + .usingRecursiveComparison() + .ignoringFields("ctx") + .isEqualTo(expectedMsg); + } + + @Test + public void givenForceAckIsFalseAndErrorOccursOnTheGCP_whenOnMsg_thenTellFailure() throws IOException, TbNodeException { + given(ctxMock.isExternalNodeForceAck()).willReturn(false); + willReturn(pubSubClientMock).given(node).initPubSubClient(ctxMock); + + String errorMsg = "Something went wrong!"; + ApiFuture failedFuture = ApiFutures.immediateFailedFuture(new RuntimeException(errorMsg)); + given(pubSubClientMock.publish(any())).willReturn(failedFuture); + given(ctxMock.getExternalCallExecutor()).willReturn(executor); + + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsgMetaData metaData = new TbMsgMetaData(); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + then(ctxMock).should(never()).ack(any()); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + ArgumentCaptor actualError = ArgumentCaptor.forClass(Throwable.class); + then(ctxMock).should().tellFailure(actualMsg.capture(), actualError.capture()); + metaData.putValue("error", RuntimeException.class + ": " + errorMsg); + TbMsg expectedMsg = TbMsg.transformMsgMetadata(msg, metaData); + assertThat(actualMsg.getValue()) + .usingRecursiveComparison() + .ignoringFields("ctx") + .isEqualTo(expectedMsg); + assertThat(actualError.getValue()).isInstanceOf(RuntimeException.class).hasMessage(errorMsg); + } + + @Test + public void givenForceAckIsTrueAndErrorOccursOnTheGCP_whenOnMsg_thenEnqueueForTellFailure() throws IOException, TbNodeException { + given(ctxMock.isExternalNodeForceAck()).willReturn(true); + willReturn(pubSubClientMock).given(node).initPubSubClient(ctxMock); + + String errorMsg = "Something went wrong!"; + ApiFuture failedFuture = ApiFutures.immediateFailedFuture(new RuntimeException(errorMsg)); + given(pubSubClientMock.publish(any())).willReturn(failedFuture); + given(ctxMock.getExternalCallExecutor()).willReturn(executor); + + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsgMetaData metaData = new TbMsgMetaData(); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + then(ctxMock).should().ack(msg); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + ArgumentCaptor actualError = ArgumentCaptor.forClass(Throwable.class); + then(ctxMock).should().enqueueForTellFailure(actualMsg.capture(), actualError.capture()); + metaData.putValue("error", RuntimeException.class + ": " + errorMsg); + TbMsg expectedMsg = TbMsg.transformMsgMetadata(msg, metaData); + assertThat(actualMsg.getValue()) + .usingRecursiveComparison() + .ignoringFields("ctx") + .isEqualTo(expectedMsg); + assertThat(actualError.getValue()).isInstanceOf(RuntimeException.class).hasMessage(errorMsg); + } + + @Test + public void givenPubSubClientIsNotNull_whenDestroy_thenShutDownAndAwaitTermination() throws InterruptedException { + ReflectionTestUtils.setField(node, "pubSubClient", pubSubClientMock); + node.destroy(); + then(pubSubClientMock).should().shutdown(); + then(pubSubClientMock).should().awaitTermination(1, TimeUnit.SECONDS); + } + + @Test + public void givenPubSubClientIsNull_whenDestroy_thenShutDownAndAwaitTermination() { + ReflectionTestUtils.setField(node, "pubSubClient", null); + node.destroy(); + then(pubSubClientMock).shouldHaveNoInteractions(); + } + +} diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/kafka/TbKafkaNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/kafka/TbKafkaNodeTest.java new file mode 100644 index 0000000000..add12dcec2 --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/kafka/TbKafkaNodeTest.java @@ -0,0 +1,423 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.kafka; + +import org.apache.kafka.clients.producer.Callback; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.clients.producer.RecordMetadata; +import org.apache.kafka.common.header.Headers; +import org.apache.kafka.common.header.internals.RecordHeader; +import org.apache.kafka.common.header.internals.RecordHeaders; +import org.apache.kafka.common.serialization.StringSerializer; +import org.apache.kafka.common.utils.KafkaThread; +import org.junit.jupiter.api.BeforeEach; +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.MethodSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +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.common.util.ListeningExecutor; +import org.thingsboard.rule.engine.TestDbCallbackExecutor; +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.api.util.TbNodeUtils; +import org.thingsboard.server.common.data.exception.ThingsboardKafkaClientError; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.RuleNodeId; +import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.data.msg.TbNodeConnectionType; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; + +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.mock; +import static org.mockito.BDDMockito.never; +import static org.mockito.BDDMockito.spy; +import static org.mockito.BDDMockito.then; +import static org.mockito.BDDMockito.times; +import static org.mockito.BDDMockito.willAnswer; +import static org.mockito.BDDMockito.willReturn; +import static org.mockito.BDDMockito.willThrow; + +@ExtendWith(MockitoExtension.class) +public class TbKafkaNodeTest { + + private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("5f2eac08-bd1f-4635-a6c2-437369f996cf")); + private final RuleNodeId RULE_NODE_ID = new RuleNodeId(UUID.fromString("d46bb666-ecab-4d89-a28f-5abdca23ac29")); + private final ListeningExecutor executor = new TestDbCallbackExecutor(); + + private final long OFFSET = 1; + private final int PARTITION = 0; + + private final String SERVICE_ID_STR = "test-service-id"; + private final String TEST_TOPIC = "test-topic"; + private final String TEST_KEY = "test-key"; + + private TbKafkaNode node; + private TbKafkaNodeConfiguration config; + + @Mock + private TbContext ctxMock; + @Mock + private KafkaProducer producerMock; + @Mock + private KafkaThread ioThreadMock; + @Mock + private RecordMetadata recordMetadataMock; + + @BeforeEach + public void setUp() { + node = spy(new TbKafkaNode()); + config = new TbKafkaNodeConfiguration().defaultConfiguration(); + config.setTopicPattern(TEST_TOPIC); + config.setKeyPattern(TEST_KEY); + } + + @Test + public void verifyDefaultConfig() { + config = new TbKafkaNodeConfiguration().defaultConfiguration(); + assertThat(config.getTopicPattern()).isEqualTo("my-topic"); + assertThat(config.getKeyPattern()).isNull(); + assertThat(config.getBootstrapServers()).isEqualTo("localhost:9092"); + assertThat(config.getRetries()).isEqualTo(0); + assertThat(config.getBatchSize()).isEqualTo(16384); + assertThat(config.getLinger()).isEqualTo(0); + assertThat(config.getBufferMemory()).isEqualTo(33554432); + assertThat(config.getAcks()).isEqualTo("-1"); + assertThat(config.getKeySerializer()).isEqualTo(StringSerializer.class.getName()); + assertThat(config.getValueSerializer()).isEqualTo(StringSerializer.class.getName()); + assertThat(config.getOtherProperties()).isEmpty(); + assertThat(config.isAddMetadataKeyValuesAsKafkaHeaders()).isFalse(); + assertThat(config.getKafkaHeadersCharset()).isEqualTo("UTF-8"); + } + + @Test + public void givenExceptionDuringKafkaInitialization_whenInit_thenDestroy() throws TbNodeException { + // GIVEN + given(ctxMock.getSelfId()).willReturn(RULE_NODE_ID); + ReflectionTestUtils.setField(producerMock, "ioThread", ioThreadMock); + willAnswer(invocationOnMock -> { + Thread.UncaughtExceptionHandler exceptionHandler = invocationOnMock.getArgument(0); + exceptionHandler.uncaughtException(ioThreadMock, new ThingsboardKafkaClientError("Error during init")); + return null; + }).given(ioThreadMock).setUncaughtExceptionHandler(any()); + willReturn(producerMock).given(node).getKafkaProducer(any()); + + // WHEN + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + + // THEN + then(producerMock).should().close(); + then(producerMock).shouldHaveNoMoreInteractions(); + } + + @Test + public void verifyKafkaProperties() throws TbNodeException { + String sslKeyStoreCertificateChain = "cbdvch\\nfwrg\nvgwg\\n"; + String sslKeyStoreKey = "nghmh\\nhmmnh\\\\ngreg\nvgwg\\n"; + String sslTruststoreCertificates = "grthrt\fd\\nfwrg\nvgwg\\n"; + config.setOtherProperties(Map.of( + "ssl.keystore.certificate.chain", sslKeyStoreCertificateChain, + "ssl.keystore.key", sslKeyStoreKey, + "ssl.truststore.certificates", sslTruststoreCertificates, + "ssl.protocol", "TLSv1.2" + )); + + mockSuccessfulInit(); + + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + + Properties expectedProperties = new Properties(); + expectedProperties.put(ProducerConfig.CLIENT_ID_CONFIG, "producer-tb-kafka-node-" + RULE_NODE_ID.getId() + "-" + SERVICE_ID_STR); + expectedProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, config.getBootstrapServers()); + expectedProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, config.getValueSerializer()); + expectedProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, config.getKeySerializer()); + expectedProperties.put(ProducerConfig.ACKS_CONFIG, config.getAcks()); + expectedProperties.put(ProducerConfig.RETRIES_CONFIG, config.getRetries()); + expectedProperties.put(ProducerConfig.BATCH_SIZE_CONFIG, config.getBatchSize()); + expectedProperties.put(ProducerConfig.LINGER_MS_CONFIG, config.getLinger()); + expectedProperties.put(ProducerConfig.BUFFER_MEMORY_CONFIG, config.getBufferMemory()); + expectedProperties.put("ssl.keystore.certificate.chain", sslKeyStoreCertificateChain.replace("\\n", "\n")); + expectedProperties.put("ssl.keystore.key", sslKeyStoreKey.replace("\\n", "\n")); + expectedProperties.put("ssl.truststore.certificates", sslTruststoreCertificates.replace("\\n", "\n")); + expectedProperties.put("ssl.protocol", "TLSv1.2"); + + ArgumentCaptor properties = ArgumentCaptor.forClass(Properties.class); + then(node).should().getKafkaProducer(properties.capture()); + assertThat(properties.getValue()).isEqualTo(expectedProperties); + } + + @Test + public void givenInitErrorIsNotNull_whenOnMsg_thenTellFailure() { + // GIVEN + String errorMsg = "Error during kafka initialization!"; + ReflectionTestUtils.setField(node, "config", config); + ReflectionTestUtils.setField(node, "initError", new ThingsboardKafkaClientError(errorMsg)); + + // WHEN + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + // THEN + ArgumentCaptor actualError = ArgumentCaptor.forClass(Throwable.class); + then(ctxMock).should().tellFailure(eq(msg), actualError.capture()); + assertThat(actualError.getValue()) + .isInstanceOf(RuntimeException.class) + .hasMessage("Failed to initialize Kafka rule node producer: " + errorMsg); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void givenForceAckAndExceptionWasThrown_whenOnMsg_thenTellFailure(boolean forceAck) throws TbNodeException { + // GIVEN + given(ctxMock.isExternalNodeForceAck()).willReturn(forceAck); + mockSuccessfulInit(); + ListeningExecutor executorMock = mock(ListeningExecutor.class); + given(ctxMock.getExternalCallExecutor()).willReturn(executorMock); + String errorMsg = "Something went wrong!"; + willThrow(new RuntimeException(errorMsg)).given(executorMock).executeAsync(any(Callable.class)); + + // WHEN + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + // THEN + then(ctxMock).should(forceAck ? times(1) : never()).ack(msg); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + ArgumentCaptor actualError = ArgumentCaptor.forClass(Throwable.class); + then(ctxMock).should().tellFailure(actualMsg.capture(), actualError.capture()); + assertThat(actualMsg.getValue()).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(msg); + assertThat(actualError.getValue()).isInstanceOf(RuntimeException.class).hasMessage(errorMsg); + } + + @ParameterizedTest + @MethodSource + public void givenForceAckIsTrueTopicAndKeyPatternsAndAddMetadataKeyValuesAsKafkaHeadersIsFalse_whenOnMsg_thenEnqueueForTellNext( + String topicPattern, String keyPattern, TbMsgMetaData metaData, String data + ) throws TbNodeException { + // GIVEN + config.setTopicPattern(topicPattern); + config.setKeyPattern(keyPattern); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, data); + String topic = TbNodeUtils.processPattern(topicPattern, msg); + String key = TbNodeUtils.processPattern(keyPattern, msg); + + given(ctxMock.isExternalNodeForceAck()).willReturn(true); + mockSuccessfulInit(); + mockSuccessfulPublishingRequest(topic); + + // WHEN + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + node.onMsg(ctxMock, msg); + + // THEN + then(ctxMock).should().ack(msg); + verifyProducerRecord(topic, key, msg.getData()); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + then(ctxMock).should().enqueueForTellNext(actualMsg.capture(), eq(TbNodeConnectionType.SUCCESS)); + verifyOutgoingSuccessMsg(topic, actualMsg.getValue(), msg); + } + + private static Stream givenForceAckIsTrueTopicAndKeyPatternsAndAddMetadataKeyValuesAsKafkaHeadersIsFalse_whenOnMsg_thenEnqueueForTellNext() { + return Stream.of( + Arguments.of("test-topic", "test-key", new TbMsgMetaData(), TbMsg.EMPTY_JSON_OBJECT), + Arguments.of("${mdTopicPattern}", "${mdKeyPattern}", new TbMsgMetaData( + Map.of( + "mdTopicPattern", "md-test-topic", + "mdKeyPattern", "md-test-key" + )), TbMsg.EMPTY_JSON_OBJECT), + Arguments.of("$[msgTopicPattern]", "$[msgKeyPattern]", new TbMsgMetaData(), + "{\"msgTopicPattern\":\"msg-test-topic\",\"msgKeyPattern\":\"msg-test-key\"}") + ); + } + + @ParameterizedTest + @NullAndEmptySource + public void givenForceAckIsFalseAndKeyIsNullOrEmptyAndErrorOccursDuringPublishing_whenOnMsg_thenTellFailure(String key) throws TbNodeException { + // GIVEN + config.setKeyPattern(key); + + given(ctxMock.isExternalNodeForceAck()).willReturn(false); + mockSuccessfulInit(); + String errorMsg = "Something went wrong!"; + mockFailedPublishingRequest(new RuntimeException(errorMsg)); + + // WHEN + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + // THEN + verifyProducerRecord(TEST_TOPIC, null, msg.getData()); + then(ctxMock).should(never()).ack(msg); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + ArgumentCaptor actualError = ArgumentCaptor.forClass(Throwable.class); + then(ctxMock).should().tellFailure(actualMsg.capture(), actualError.capture()); + verifyOutgoingFailureMsg(errorMsg, actualMsg.getValue(), msg); + } + + @Test + public void givenForceAckIsTrueAndAddKafkaHeadersIsTrueAndToBytesCharsetIsNullAndErrorOccursDuringPublishing_whenOnMsg_thenEnqueueForTellFailure() throws TbNodeException { + // GIVEN + config.setAddMetadataKeyValuesAsKafkaHeaders(true); + config.setKafkaHeadersCharset(null); + + given(ctxMock.isExternalNodeForceAck()).willReturn(true); + mockSuccessfulInit(); + String errorMsg = "Something went wrong!"; + mockFailedPublishingRequest(new RuntimeException(errorMsg)); + + // WHEN + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + // THEN + then(ctxMock).should().ack(msg); + Headers expectedHeaders = new RecordHeaders(); + msg.getMetaData().values().forEach((k, v) -> expectedHeaders.add(new RecordHeader("tb_msg_md_" + k, v.getBytes(StandardCharsets.UTF_8)))); + verifyProducerRecord(TEST_TOPIC, TEST_KEY, msg.getData(), expectedHeaders); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + ArgumentCaptor actualError = ArgumentCaptor.forClass(Throwable.class); + then(ctxMock).should().enqueueForTellFailure(actualMsg.capture(), actualError.capture()); + verifyOutgoingFailureMsg(errorMsg, actualMsg.getValue(), msg); + } + + @Test + public void givenForceAckIsFalseAndAddMetadataKeyValuesAsKafkaHeadersIsTrueAndToBytesCharsetIsSet_whenOnMsg_thenTellSuccess() throws TbNodeException { + // GIVEN + config.setAddMetadataKeyValuesAsKafkaHeaders(true); + config.setKafkaHeadersCharset("UTF-16"); + + given(ctxMock.isExternalNodeForceAck()).willReturn(false); + mockSuccessfulInit(); + mockSuccessfulPublishingRequest(TEST_TOPIC); + + // WHEN + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("key", "value"); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + // THEN + then(ctxMock).should(never()).ack(msg); + Headers expectedHeaders = new RecordHeaders(); + msg.getMetaData().values().forEach((k, v) -> expectedHeaders.add(new RecordHeader("tb_msg_md_" + k, v.getBytes(StandardCharsets.UTF_16)))); + verifyProducerRecord(TEST_TOPIC, TEST_KEY, msg.getData(), expectedHeaders); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + then(ctxMock).should().tellSuccess(actualMsg.capture()); + verifyOutgoingSuccessMsg(TEST_TOPIC, actualMsg.getValue(), msg); + } + + @Test + public void givenProducerIsNotNull_whenDestroy_thenShouldClose() { + ReflectionTestUtils.setField(node, "producer", producerMock); + node.destroy(); + then(producerMock).should().close(); + } + + @Test + public void givenProducerIsNull_whenDestroy_thenDoNothing() { + node.destroy(); + then(producerMock).shouldHaveNoInteractions(); + } + + private void mockSuccessfulInit() { + given(ctxMock.getSelfId()).willReturn(RULE_NODE_ID); + given(ctxMock.getServiceId()).willReturn(SERVICE_ID_STR); + ReflectionTestUtils.setField(producerMock, "ioThread", ioThreadMock); + willReturn(producerMock).given(node).getKafkaProducer(any()); + } + + private void mockSuccessfulPublishingRequest(String topic) { + given(ctxMock.getExternalCallExecutor()).willReturn(executor); + willAnswer(invocation -> { + Callback callback = invocation.getArgument(1); + callback.onCompletion(recordMetadataMock, null); + return null; + }).given(producerMock).send(any(), any(Callback.class)); + given(recordMetadataMock.offset()).willReturn(OFFSET); + given(recordMetadataMock.partition()).willReturn(PARTITION); + given(recordMetadataMock.topic()).willReturn(topic); + } + + private void mockFailedPublishingRequest(Exception exception) { + given(ctxMock.getExternalCallExecutor()).willReturn(executor); + willAnswer(invocation -> { + Callback callback = invocation.getArgument(1); + callback.onCompletion(recordMetadataMock, exception); + return null; + }).given(producerMock).send(any(), any(Callback.class)); + } + + private void verifyProducerRecord(String expectedTopic, String expectedKey, String expectedValue) { + verifyProducerRecord(expectedTopic, expectedKey, expectedValue, null); + } + + private void verifyProducerRecord(String expectedTopic, String expectedKey, String expectedValue, Headers expectedHeaders) { + ArgumentCaptor> actualRecordCaptor = ArgumentCaptor.forClass(ProducerRecord.class); + then(producerMock).should().send(actualRecordCaptor.capture(), any()); + ProducerRecord actualRecord = actualRecordCaptor.getValue(); + assertThat(actualRecord.topic()).isEqualTo(expectedTopic); + assertThat(actualRecord.key()).isEqualTo(expectedKey); + assertThat(actualRecord.value()).isEqualTo(expectedValue); + if (expectedHeaders != null) { + assertThat(actualRecord.headers()).isEqualTo(expectedHeaders); + } + } + + private void verifyOutgoingSuccessMsg(String expectedTopic, TbMsg actualMsg, TbMsg originalMsg) { + TbMsgMetaData metaData = originalMsg.getMetaData().copy(); + metaData.putValue("offset", String.valueOf(OFFSET)); + metaData.putValue("partition", String.valueOf(PARTITION)); + metaData.putValue("topic", expectedTopic); + TbMsg expectedMsg = TbMsg.transformMsgMetadata(originalMsg, metaData); + assertThat(actualMsg) + .usingRecursiveComparison() + .ignoringFields("ctx") + .isEqualTo(expectedMsg); + } + + private void verifyOutgoingFailureMsg(String errorMsg, TbMsg actualMsg, TbMsg originalMsg) { + TbMsgMetaData metaData = originalMsg.getMetaData(); + metaData.putValue("error", RuntimeException.class + ": " + errorMsg); + TbMsg expectedMsg = TbMsg.transformMsgMetadata(originalMsg, metaData); + assertThat(actualMsg).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(expectedMsg); + } + +} 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 9eb74b5627..84bbafe825 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 @@ -15,20 +15,21 @@ */ package org.thingsboard.rule.engine.metadata; -import com.datastax.oss.driver.api.core.uuid.Uuids; -import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.Futures; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.provider.Arguments; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.thingsboard.common.util.AbstractListeningExecutor; import org.thingsboard.common.util.JacksonUtil; +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.util.TbMsgSource; @@ -43,7 +44,6 @@ import org.thingsboard.server.common.data.kv.JsonDataEntry; import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.msg.TbMsgType; -import org.thingsboard.server.common.data.util.TbPair; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.dao.attributes.AttributesService; @@ -51,25 +51,26 @@ import org.thingsboard.server.dao.timeseries.TimeseriesService; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -public class TbGetAttributesNodeTest { +public class TbGetAttributesNodeTest extends AbstractRuleNodeUpgradeTest { - private static final EntityId ORIGINATOR = new DeviceId(Uuids.timeBased()); - private static final TenantId TENANT_ID = TenantId.fromUUID(Uuids.timeBased()); + private final EntityId ORIGINATOR_ID = new DeviceId(UUID.fromString("965f2975-787a-4f21-87e6-9aa4738186ff")); + private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("befd3239-79b8-4263-a8d1-95b69f44f798")); private AbstractListeningExecutor dbExecutor; @Mock @@ -84,6 +85,8 @@ public class TbGetAttributesNodeTest { private List sharedAttributes; private List tsKeys; private long ts; + + @Spy private TbGetAttributesNode node; @BeforeEach @@ -107,16 +110,16 @@ public class TbGetAttributesNodeTest { tsKeys = List.of("temperature", "humidity", "unknown"); ts = System.currentTimeMillis(); - lenient().when(attributesServiceMock.find(TENANT_ID, ORIGINATOR, AttributeScope.CLIENT_SCOPE, clientAttributes)) + lenient().when(attributesServiceMock.find(TENANT_ID, ORIGINATOR_ID, AttributeScope.CLIENT_SCOPE, clientAttributes)) .thenReturn(Futures.immediateFuture(getListAttributeKvEntry(clientAttributes, ts))); - lenient().when(attributesServiceMock.find(TENANT_ID, ORIGINATOR, AttributeScope.SERVER_SCOPE, serverAttributes)) + lenient().when(attributesServiceMock.find(TENANT_ID, ORIGINATOR_ID, AttributeScope.SERVER_SCOPE, serverAttributes)) .thenReturn(Futures.immediateFuture(getListAttributeKvEntry(serverAttributes, ts))); - lenient().when(attributesServiceMock.find(TENANT_ID, ORIGINATOR, AttributeScope.SHARED_SCOPE, sharedAttributes)) + lenient().when(attributesServiceMock.find(TENANT_ID, ORIGINATOR_ID, AttributeScope.SHARED_SCOPE, sharedAttributes)) .thenReturn(Futures.immediateFuture(getListAttributeKvEntry(sharedAttributes, ts))); - lenient().when(timeseriesServiceMock.findLatest(TENANT_ID, ORIGINATOR, tsKeys)) + lenient().when(timeseriesServiceMock.findLatest(TENANT_ID, ORIGINATOR_ID, tsKeys)) .thenReturn(Futures.immediateFuture(getListTsKvEntry(tsKeys, ts))); } @@ -129,7 +132,7 @@ public class TbGetAttributesNodeTest { public void givenFetchAttributesToMetadata_whenOnMsg_thenShouldTellSuccess() throws Exception { // GIVEN node = initNode(TbMsgSource.METADATA, false, false); - var msg = getTbMsg(ORIGINATOR); + var msg = getTbMsg(ORIGINATOR_ID); // WHEN node.onMsg(ctxMock, msg); @@ -148,7 +151,7 @@ public class TbGetAttributesNodeTest { public void givenFetchLatestTimeseriesToMetadata_whenOnMsg_thenShouldTellSuccess() throws Exception { // GIVEN node = initNode(TbMsgSource.METADATA, true, false); - var msg = getTbMsg(ORIGINATOR); + var msg = getTbMsg(ORIGINATOR_ID); // WHEN node.onMsg(ctxMock, msg); @@ -167,7 +170,7 @@ public class TbGetAttributesNodeTest { public void givenFetchAttributesToData_whenOnMsg_thenShouldTellSuccess() throws Exception { // GIVEN node = initNode(TbMsgSource.DATA, false, false); - var msg = getTbMsg(ORIGINATOR); + var msg = getTbMsg(ORIGINATOR_ID); // WHEN node.onMsg(ctxMock, msg); @@ -186,7 +189,7 @@ public class TbGetAttributesNodeTest { public void givenFetchLatestTimeseriesToData_whenOnMsg_thenShouldTellSuccess() throws Exception { // GIVEN node = initNode(TbMsgSource.DATA, true, false); - var msg = getTbMsg(ORIGINATOR); + var msg = getTbMsg(ORIGINATOR_ID); // WHEN node.onMsg(ctxMock, msg); @@ -205,7 +208,7 @@ public class TbGetAttributesNodeTest { public void givenFetchAttributesToMetadata_whenOnMsg_thenShouldTellFailure() throws Exception { // GIVEN node = initNode(TbMsgSource.METADATA, false, true); - var msg = getTbMsg(ORIGINATOR); + var msg = getTbMsg(ORIGINATOR_ID); // WHEN node.onMsg(ctxMock, msg); @@ -224,7 +227,7 @@ public class TbGetAttributesNodeTest { public void givenFetchLatestTimeseriesToData_whenOnMsg_thenShouldTellFailure() throws Exception { // GIVEN node = initNode(TbMsgSource.DATA, true, true); - var msg = getTbMsg(ORIGINATOR); + var msg = getTbMsg(ORIGINATOR_ID); // WHEN node.onMsg(ctxMock, msg); @@ -243,7 +246,7 @@ public class TbGetAttributesNodeTest { public void givenFetchLatestTimeseriesToDataAndDataIsNotJsonObject_whenOnMsg_thenException() throws Exception { // GIVEN node = initNode(TbMsgSource.DATA, true, true); - var msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, ORIGINATOR, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_ARRAY); + var msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, ORIGINATOR_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_ARRAY); // WHEN var exception = assertThrows(IllegalArgumentException.class, () -> node.onMsg(ctxMock, msg)); @@ -253,56 +256,6 @@ public class TbGetAttributesNodeTest { assertThat(exception.getMessage()).isEqualTo("Message body is not an object!"); } - @Test - public void givenOldConfig_whenUpgrade_thenShouldReturnTrueResultWithNewConfig() throws Exception { - var defaultConfig = new TbGetAttributesNodeConfiguration().defaultConfiguration(); - var node = new TbGetAttributesNode(); - String oldConfig = "{\"fetchToData\":false," + - "\"clientAttributeNames\":[]," + - "\"sharedAttributeNames\":[]," + - "\"serverAttributeNames\":[]," + - "\"latestTsKeyNames\":[]," + - "\"tellFailureIfAbsent\":true," + - "\"getLatestValueWithTs\":false}"; - JsonNode configJson = JacksonUtil.toJsonNode(oldConfig); - TbPair upgrade = node.upgrade(0, configJson); - Assertions.assertTrue(upgrade.getFirst()); - Assertions.assertEquals(defaultConfig, JacksonUtil.treeToValue(upgrade.getSecond(), defaultConfig.getClass())); - } - - @Test - public void givenOldConfigWithNoFetchToDataProperty_whenUpgrade_thenShouldReturnTrueResultWithNewConfig() throws Exception { - var defaultConfig = new TbGetAttributesNodeConfiguration().defaultConfiguration(); - var node = new TbGetAttributesNode(); - String oldConfig = "{\"clientAttributeNames\":[]," + - "\"sharedAttributeNames\":[]," + - "\"serverAttributeNames\":[]," + - "\"latestTsKeyNames\":[]," + - "\"tellFailureIfAbsent\":true," + - "\"getLatestValueWithTs\":false}"; - JsonNode configJson = JacksonUtil.toJsonNode(oldConfig); - TbPair upgrade = node.upgrade(0, configJson); - Assertions.assertTrue(upgrade.getFirst()); - Assertions.assertEquals(defaultConfig, JacksonUtil.treeToValue(upgrade.getSecond(), defaultConfig.getClass())); - } - - @Test - public void givenOldConfigWithNullFetchToDataProperty_whenUpgrade_thenShouldReturnTrueResultWithNewConfig() throws Exception { - var defaultConfig = new TbGetAttributesNodeConfiguration().defaultConfiguration(); - var node = new TbGetAttributesNode(); - String oldConfig = "{\"fetchToData\":null," + - "\"clientAttributeNames\":[]," + - "\"sharedAttributeNames\":[]," + - "\"serverAttributeNames\":[]," + - "\"latestTsKeyNames\":[]," + - "\"tellFailureIfAbsent\":true," + - "\"getLatestValueWithTs\":false}"; - JsonNode configJson = JacksonUtil.toJsonNode(oldConfig); - TbPair upgrade = node.upgrade(0, configJson); - Assertions.assertTrue(upgrade.getFirst()); - Assertions.assertEquals(defaultConfig, JacksonUtil.treeToValue(upgrade.getSecond(), defaultConfig.getClass())); - } - private TbMsg checkMsg(boolean checkSuccess) { var msgCaptor = ArgumentCaptor.forClass(TbMsg.class); if (checkSuccess) { @@ -421,4 +374,117 @@ public class TbGetAttributesNodeTest { return kvEntriesList; } + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { + return Stream.of( + // config for version 1 with upgrade from version 0 + Arguments.of(0, + """ + { + "fetchToData":false, + "clientAttributeNames":[], + "sharedAttributeNames":[], + "serverAttributeNames":[], + "latestTsKeyNames":[], + "tellFailureIfAbsent":true, + "getLatestValueWithTs":false + } + """, + true, + """ + { + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """ + ), + // config for version 1 with upgrade from version 0 (old config with no fetchToData property) + Arguments.of(0, + """ + { + "clientAttributeNames":[], + "sharedAttributeNames":[],"serverAttributeNames":[], + "latestTsKeyNames":[], + "tellFailureIfAbsent":true, + "getLatestValueWithTs":false + } + """, + true, + """ + { + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """ + ), + // config for version 1 with upgrade from version 0 (old config with null fetchToData property) + Arguments.of(0, + """ + { + "fetchToData":null, + "clientAttributeNames":[], + "sharedAttributeNames":[], + "serverAttributeNames":[], + "latestTsKeyNames":[], + "tellFailureIfAbsent":true, + "getLatestValueWithTs":false + } + """, + true, + """ + { + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """ + ), + // config for version 1 with upgrade from version 1 + Arguments.of(1, + """ + { + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """, + false, + """ + { + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """ + ) + ); + + } + + @Override + protected TbNode getTestNode() { + return node; + } + } 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 ac6bb38be5..8cacf33f79 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 @@ -15,68 +15,236 @@ */ package org.thingsboard.rule.engine.metadata; -import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.util.concurrent.Futures; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.provider.Arguments; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import org.thingsboard.common.util.JacksonUtil; -import org.thingsboard.server.common.data.util.TbPair; +import org.thingsboard.common.util.ListeningExecutor; +import org.thingsboard.rule.engine.AbstractRuleNodeUpgradeTest; +import org.thingsboard.rule.engine.TestDbCallbackExecutor; +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.data.DeviceRelationsQuery; +import org.thingsboard.rule.engine.util.TbMsgSource; +import org.thingsboard.server.common.data.device.DeviceSearchQuery; +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.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.EntitySearchDirection; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.dao.device.DeviceService; -public class TbGetDeviceAttrNodeTest { +import java.util.Arrays; +import java.util.Collections; +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.stream.Stream; + +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.given; +import static org.mockito.BDDMockito.spy; +import static org.mockito.BDDMockito.then; + +@ExtendWith(MockitoExtension.class) +public class TbGetDeviceAttrNodeTest extends AbstractRuleNodeUpgradeTest { + + private final TenantId TENANT_ID = new TenantId(UUID.fromString("5aea576c-66c4-4732-86b8-dc6bfcde7443")); + private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("40b6b393-6ddf-47f9-973a-18550ca70384")); + private final ListeningExecutor executor = new TestDbCallbackExecutor(); + + + private TbGetDeviceAttrNode node; + private TbGetDeviceAttrNodeConfiguration config; + + @Mock + private TbContext ctxMock; + @Mock + private DeviceService deviceServiceMock; + + @BeforeEach + public void setUp() { + node = spy(new TbGetDeviceAttrNode()); + config = new TbGetDeviceAttrNodeConfiguration().defaultConfiguration(); + } @Test - public void givenOldConfig_whenUpgrade_thenShouldReturnTrueResultWithNewConfig() throws Exception { - var defaultConfig = new TbGetDeviceAttrNodeConfiguration().defaultConfiguration(); - var node = new TbGetDeviceAttrNode(); - String oldConfig = "{\"fetchToData\":false," + - "\"clientAttributeNames\":[]," + - "\"sharedAttributeNames\":[]," + - "\"serverAttributeNames\":[]," + - "\"latestTsKeyNames\":[]," + - "\"tellFailureIfAbsent\":true," + - "\"getLatestValueWithTs\":false," + - "\"deviceRelationsQuery\":{\"direction\":\"FROM\",\"maxLevel\":1,\"relationType\":\"Contains\",\"deviceTypes\":[\"default\"]," + - "\"fetchLastLevelOnly\":false}}"; - JsonNode configJson = JacksonUtil.toJsonNode(oldConfig); - TbPair upgrade = node.upgrade(0, configJson); - Assertions.assertTrue(upgrade.getFirst()); - Assertions.assertEquals(defaultConfig, JacksonUtil.treeToValue(upgrade.getSecond(), defaultConfig.getClass())); + public void verifyDefaultConfig() { + assertThat(config.getClientAttributeNames()).isEmpty(); + assertThat(config.getSharedAttributeNames()).isEmpty(); + assertThat(config.getServerAttributeNames()).isEmpty(); + assertThat(config.getLatestTsKeyNames()).isEmpty(); + assertThat(config.isTellFailureIfAbsent()).isTrue(); + assertThat(config.isGetLatestValueWithTs()).isFalse(); + assertThat(config.getFetchTo()).isEqualTo(TbMsgSource.METADATA); + + var deviceRelationsQuery = new DeviceRelationsQuery(); + deviceRelationsQuery.setDirection(EntitySearchDirection.FROM); + deviceRelationsQuery.setMaxLevel(1); + deviceRelationsQuery.setRelationType(EntityRelation.CONTAINS_TYPE); + deviceRelationsQuery.setDeviceTypes(Collections.singletonList("default")); + + assertThat(config.getDeviceRelationsQuery()).isEqualTo(deviceRelationsQuery); } @Test - public void givenOldConfigWithNoFetchToDataProperty_whenUpgrade_thenShouldReturnTrueResultWithNewConfig() throws Exception { - var defaultConfig = new TbGetDeviceAttrNodeConfiguration().defaultConfiguration(); - var node = new TbGetDeviceAttrNode(); - String oldConfig = "{\"clientAttributeNames\":[]," + - "\"sharedAttributeNames\":[]," + - "\"serverAttributeNames\":[]," + - "\"latestTsKeyNames\":[]," + - "\"tellFailureIfAbsent\":true," + - "\"getLatestValueWithTs\":false," + - "\"deviceRelationsQuery\":{\"direction\":\"FROM\",\"maxLevel\":1,\"relationType\":\"Contains\",\"deviceTypes\":[\"default\"]," + - "\"fetchLastLevelOnly\":false}}"; - JsonNode configJson = JacksonUtil.toJsonNode(oldConfig); - TbPair upgrade = node.upgrade(0, configJson); - Assertions.assertTrue(upgrade.getFirst()); - Assertions.assertEquals(defaultConfig, JacksonUtil.treeToValue(upgrade.getSecond(), defaultConfig.getClass())); + public void givenFetchToIsNull_whenInit_thenThrowsException() { + config.setFetchTo(null); + assertThatThrownBy(() -> node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) + .isInstanceOf(TbNodeException.class) + .hasMessage("FetchTo option can't be null! Allowed values: " + Arrays.toString(TbMsgSource.values())); } @Test - public void givenOldConfigWithNullFetchToDataProperty_whenUpgrade_thenShouldReturnTrueResultWithNewConfig() throws Exception { - var defaultConfig = new TbGetDeviceAttrNodeConfiguration().defaultConfiguration(); - var node = new TbGetDeviceAttrNode(); - String oldConfig = "{\"fetchToData\":null," + - "\"clientAttributeNames\":[]," + - "\"sharedAttributeNames\":[]," + - "\"serverAttributeNames\":[]," + - "\"latestTsKeyNames\":[]," + - "\"tellFailureIfAbsent\":true," + - "\"getLatestValueWithTs\":false," + - "\"deviceRelationsQuery\":{\"direction\":\"FROM\",\"maxLevel\":1,\"relationType\":\"Contains\",\"deviceTypes\":[\"default\"]," + - "\"fetchLastLevelOnly\":false}}"; - JsonNode configJson = JacksonUtil.toJsonNode(oldConfig); - TbPair upgrade = node.upgrade(0, configJson); - Assertions.assertTrue(upgrade.getFirst()); - Assertions.assertEquals(defaultConfig, JacksonUtil.treeToValue(upgrade.getSecond(), defaultConfig.getClass())); + public void givenDeviceDoesNotExist_whenOnMsg_thenTellFailure() throws TbNodeException { + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + + given(ctxMock.getDeviceService()).willReturn(deviceServiceMock); + given(ctxMock.getTenantId()).willReturn(TENANT_ID); + given(deviceServiceMock.findDevicesByQuery(any(TenantId.class), any(DeviceSearchQuery.class))).willReturn(Futures.immediateFuture(Collections.emptyList())); + given(ctxMock.getDbCallbackExecutor()).willReturn(executor); + + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + ArgumentCaptor actualException = ArgumentCaptor.forClass(Throwable.class); + then(ctxMock).should().tellFailure(eq(msg), actualException.capture()); + assertThat(actualException.getValue()) + .isInstanceOf(NoSuchElementException.class) + .hasMessage("Failed to find related device to message originator using relation query specified in the configuration!"); + } + + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { + return Stream.of( + // config for version 1 with upgrade from version 0 + Arguments.of(0, + """ + { + "fetchToData":false, + "clientAttributeNames":[], + "sharedAttributeNames":[], + "serverAttributeNames":[], + "latestTsKeyNames":[], + "tellFailureIfAbsent":true, + "getLatestValueWithTs":false, + "deviceRelationsQuery":{"direction":"FROM","maxLevel":1,"relationType":"Contains","deviceTypes":["default"],"fetchLastLevelOnly":false} + } + """, + true, + """ + { + "deviceRelationsQuery": {"direction": "FROM","maxLevel": 1, "relationType": "Contains","deviceTypes": ["default"],"fetchLastLevelOnly": false}, + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """ + ), + // config for version 1 with upgrade from version 0 (old config with no fetchToData property) + Arguments.of(0, + """ + { + "clientAttributeNames":[], + "sharedAttributeNames":[], + "serverAttributeNames":[], + "latestTsKeyNames":[], + "tellFailureIfAbsent":true, + "getLatestValueWithTs":false, + "deviceRelationsQuery":{"direction":"FROM","maxLevel":1,"relationType":"Contains","deviceTypes":["default"],"fetchLastLevelOnly":false} + } + """, + true, + """ + { + "deviceRelationsQuery": {"direction": "FROM","maxLevel": 1, "relationType": "Contains","deviceTypes": ["default"],"fetchLastLevelOnly": false}, + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """ + ), + // config for version 1 with upgrade from version 0 (old config with null fetchToData property) + Arguments.of(0, + """ + { + "fetchToData":null, + "clientAttributeNames":[], + "sharedAttributeNames":[], + "serverAttributeNames":[], + "latestTsKeyNames":[], + "tellFailureIfAbsent":true, + "getLatestValueWithTs":false, + "deviceRelationsQuery":{"direction":"FROM","maxLevel":1,"relationType":"Contains","deviceTypes":["default"],"fetchLastLevelOnly":false} + } + """, + true, + """ + { + "deviceRelationsQuery": {"direction": "FROM","maxLevel": 1, "relationType": "Contains","deviceTypes": ["default"],"fetchLastLevelOnly": false}, + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """ + ), + // config for version 1 with upgrade from version 1 + Arguments.of(1, + """ + { + "deviceRelationsQuery": {"direction": "FROM","maxLevel": 1, "relationType": "Contains","deviceTypes": ["default"],"fetchLastLevelOnly": false}, + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """, + false, + """ + { + "deviceRelationsQuery": {"direction": "FROM","maxLevel": 1, "relationType": "Contains","deviceTypes": ["default"],"fetchLastLevelOnly": false}, + "tellFailureIfAbsent": true, + "fetchTo": "METADATA", + "clientAttributeNames": [], + "sharedAttributeNames": [], + "serverAttributeNames": [], + "latestTsKeyNames": [], + "getLatestValueWithTs": false + } + """ + ) + ); + + } + + @Override + protected TbNode getTestNode() { + return node; } } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/TbMqttNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/TbMqttNodeTest.java index b46ecdf6fe..da568eefbb 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/TbMqttNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/TbMqttNodeTest.java @@ -15,26 +15,304 @@ */ package org.thingsboard.rule.engine.mqtt; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.EventLoopGroup; +import io.netty.handler.codec.mqtt.MqttConnectReturnCode; +import io.netty.handler.codec.mqtt.MqttQoS; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; +import io.netty.util.concurrent.Promise; import org.junit.jupiter.api.BeforeEach; +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.mockito.Spy; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; +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.mqtt.MqttClient; +import org.thingsboard.mqtt.MqttClientConfig; +import org.thingsboard.mqtt.MqttConnectResult; 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.api.util.TbNodeUtils; +import org.thingsboard.rule.engine.credentials.AnonymousCredentials; +import org.thingsboard.rule.engine.credentials.BasicCredentials; +import org.thingsboard.rule.engine.credentials.CertPemCredentials; +import org.thingsboard.server.common.data.id.DeviceId; +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.data.msg.TbNodeConnectionType; +import org.thingsboard.server.common.data.rule.RuleNode; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.stream.Stream; -import static org.mockito.Mockito.mock; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.mock; +import static org.mockito.BDDMockito.never; +import static org.mockito.BDDMockito.spy; +import static org.mockito.BDDMockito.then; +import static org.mockito.BDDMockito.willAnswer; +import static org.mockito.BDDMockito.willReturn; @ExtendWith(MockitoExtension.class) -class TbMqttNodeTest extends AbstractRuleNodeUpgradeTest { - @Spy - TbMqttNode node; +public class TbMqttNodeTest extends AbstractRuleNodeUpgradeTest { + + private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("d0c5d2a8-3a6e-4c95-8caf-47fbdc8ef98f")); + private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("09115d92-d333-432a-868c-ccd6e89c9287")); + private final RuleNodeId RULE_NODE_ID = new RuleNodeId(UUID.fromString("11699e8f-c3f0-4366-9334-cbf75798314b")); + + protected TbMqttNode mqttNode; + protected TbMqttNodeConfiguration mqttNodeConfig; + + @Mock + protected TbContext ctxMock; + @Mock + protected MqttClient mqttClientMock; + @Mock + protected EventLoopGroup eventLoopGroupMock; + @Mock + protected Promise promiseMock; + @Mock + protected MqttConnectResult resultMock; @BeforeEach - public void setUp() throws Exception { - node = mock(TbMqttNode.class); + protected void setUp() { + mqttNode = spy(new TbMqttNode()); + mqttNodeConfig = new TbMqttNodeConfiguration().defaultConfiguration(); + } + + @Test + public void verifyDefaultConfig() { + assertThat(mqttNodeConfig.getTopicPattern()).isEqualTo("my-topic"); + assertThat(mqttNodeConfig.getHost()).isNull(); + assertThat(mqttNodeConfig.getPort()).isEqualTo(1883); + assertThat(mqttNodeConfig.getConnectTimeoutSec()).isEqualTo(10); + assertThat(mqttNodeConfig.getClientId()).isNull(); + assertThat(mqttNodeConfig.isAppendClientIdSuffix()).isFalse(); + assertThat(mqttNodeConfig.isRetainedMessage()).isFalse(); + assertThat(mqttNodeConfig.isCleanSession()).isTrue(); + assertThat(mqttNodeConfig.isSsl()).isFalse(); + assertThat(mqttNodeConfig.isParseToPlainText()).isFalse(); + assertThat(mqttNodeConfig.getCredentials()).isInstanceOf(AnonymousCredentials.class); + } + + @Test + public void verifyGetOwnerIdMethod() { + given(ctxMock.getTenantId()).willReturn(TENANT_ID); + given(ctxMock.getSelf()).willReturn(new RuleNode(RULE_NODE_ID)); + + String actualOwnerIdStr = mqttNode.getOwnerId(ctxMock); + String expectedOwnerIdStr = "Tenant[" + TENANT_ID.getId() + "]RuleNode[" + RULE_NODE_ID.getId() + "]"; + assertThat(actualOwnerIdStr).isEqualTo(expectedOwnerIdStr); + } + + @Test + public void verifyPrepareMqttClientConfigMethodWithBasicCredentials() throws Exception { + BasicCredentials credentials = new BasicCredentials(); + credentials.setUsername("test_username"); + credentials.setPassword("test_password"); + mqttNodeConfig.setCredentials(credentials); + + mockSuccessfulInit(); + mqttNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(mqttNodeConfig))); + + MqttClientConfig mqttClientConfig = new MqttClientConfig(); + mqttNode.prepareMqttClientConfig(mqttClientConfig); + + assertThat(mqttClientConfig.getUsername()).isEqualTo("test_username"); + assertThat(mqttClientConfig.getPassword()).isEqualTo("test_password"); + } + + @Test + public void givenSslIsTrueAndCredentials_whenGetSslContext_thenVerifySslContext() throws Exception { + mqttNodeConfig.setSsl(true); + mqttNodeConfig.setCredentials(new BasicCredentials()); + + mockSuccessfulInit(); + mqttNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(mqttNodeConfig))); + + ArgumentCaptor mqttClientConfig = ArgumentCaptor.forClass(MqttClientConfig.class); + then(mqttNode).should().prepareMqttClientConfig(mqttClientConfig.capture()); + SslContext actualSslContext = mqttClientConfig.getValue().getSslContext(); + assertThat(actualSslContext) + .usingRecursiveComparison() + .ignoringFields("ctx", "ctxLock", "sessionContext.context.ctx", "sessionContext.context.ctxLock") + .isEqualTo(SslContextBuilder.forClient().build()); + } + + @Test + public void givenSslIsFalse_whenGetSslContext_thenVerifySslContextIsNull() throws Exception { + mqttNodeConfig.setSsl(false); + + mockSuccessfulInit(); + mqttNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(mqttNodeConfig))); + + ArgumentCaptor mqttClientConfig = ArgumentCaptor.forClass(MqttClientConfig.class); + then(mqttNode).should().prepareMqttClientConfig(mqttClientConfig.capture()); + SslContext actualSslContext = mqttClientConfig.getValue().getSslContext(); + assertThat(actualSslContext).isNull(); + } + + @Test + public void givenSuccessfulConnectResult_whenInit_thenOk() throws Exception { + mqttNodeConfig.setClientId("bfrbTESTmfkr23"); + mqttNodeConfig.setAppendClientIdSuffix(true); + mqttNodeConfig.setCredentials(new CertPemCredentials()); + + mockSuccessfulInit(); + + assertThatNoException().isThrownBy(() -> mqttNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(mqttNodeConfig)))); + } + + @Test + public void givenFailedByTimeoutConnectResult_whenInit_thenThrowsException() throws ExecutionException, InterruptedException, TimeoutException { + mqttNodeConfig.setHost("localhost"); + mqttNodeConfig.setClientId("bfrbTESTmfkr23"); + mqttNodeConfig.setCredentials(new CertPemCredentials()); + + mockConnectClient(); + given(promiseMock.get(anyLong(), any(TimeUnit.class))).willThrow(new TimeoutException("Failed to connect")); + + assertThatThrownBy(() -> mqttNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(mqttNodeConfig)))) + .isInstanceOf(TbNodeException.class) + .hasMessage("java.lang.RuntimeException: Failed to connect to MQTT broker at localhost:1883.") + .extracting(e -> ((TbNodeException) e).isUnrecoverable()) + .isEqualTo(false); + } + + @Test + public void givenFailedConnectResult_whenInit_thenThrowsException() throws Exception { + mqttNodeConfig.setHost("localhost"); + mqttNodeConfig.setClientId("bfrbTESTmfkr23"); + mqttNodeConfig.setAppendClientIdSuffix(true); + mqttNodeConfig.setCredentials(new CertPemCredentials()); + + mockConnectClient(); + given(promiseMock.get(anyLong(), any(TimeUnit.class))).willReturn(resultMock); + given(resultMock.isSuccess()).willReturn(false); + given(resultMock.getReturnCode()).willReturn(MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED); + + assertThatThrownBy(() -> mqttNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(mqttNodeConfig)))) + .isInstanceOf(TbNodeException.class) + .hasMessage("java.lang.RuntimeException: Failed to connect to MQTT broker at localhost:1883. Result code is: CONNECTION_REFUSED_NOT_AUTHORIZED") + .extracting(e -> ((TbNodeException) e).isUnrecoverable()) + .isEqualTo(false); + } + + @ParameterizedTest + @MethodSource + public void givenForceAckIsTrueAndTopicPatternAndIsRetainedMsgIsTrue_whenOnMsg_thenTellSuccess( + String topicPattern, TbMsgMetaData metaData, String data + ) throws Exception { + mqttNodeConfig.setRetainedMessage(true); + mqttNodeConfig.setTopicPattern(topicPattern); + + given(ctxMock.isExternalNodeForceAck()).willReturn(true); + mockSuccessfulInit(); + mqttNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(mqttNodeConfig))); + + Future future = mock(Future.class); + given(future.isSuccess()).willReturn(true); + given(mqttClientMock.publish(any(String.class), any(ByteBuf.class), any(MqttQoS.class), anyBoolean())).willReturn(future); + willAnswer(invocation -> { + GenericFutureListener> listener = invocation.getArgument(0); + listener.operationComplete(future); + return null; + }).given(future).addListener(any()); + + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, data); + mqttNode.onMsg(ctxMock, msg); + + then(ctxMock).should().ack(msg); + String expectedTopic = TbNodeUtils.processPattern(mqttNodeConfig.getTopicPattern(), msg); + then(mqttClientMock).should().publish(expectedTopic, Unpooled.wrappedBuffer(msg.getData().getBytes(StandardCharsets.UTF_8)), MqttQoS.AT_LEAST_ONCE, true); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + then(ctxMock).should().enqueueForTellNext(actualMsg.capture(), eq(TbNodeConnectionType.SUCCESS)); + assertThat(actualMsg.getValue()).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(msg); + } + + private static Stream givenForceAckIsTrueAndTopicPatternAndIsRetainedMsgIsTrue_whenOnMsg_thenTellSuccess() { + return Stream.of( + Arguments.of("new-topic", TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT), + Arguments.of("${md-topic-name}", new TbMsgMetaData(Map.of("md-topic-name", "md-new-topic")), TbMsg.EMPTY_JSON_OBJECT), + Arguments.of("$[msg-topic-name]", TbMsgMetaData.EMPTY, "{\"msg-topic-name\":\"msg-new-topic\"}") + ); + } + + @Test + public void givenForceAckIsFalseParseToPlainTextIsTrueAndMsgPublishingFailed_whenOnMsg_thenTellFailure() throws Exception { + mqttNodeConfig.setParseToPlainText(true); + + given(ctxMock.isExternalNodeForceAck()).willReturn(false); + mockSuccessfulInit(); + mqttNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(mqttNodeConfig))); + + Future future = mock(Future.class); + given(mqttClientMock.publish(any(String.class), any(ByteBuf.class), any(MqttQoS.class), anyBoolean())).willReturn(future); + given(future.isSuccess()).willReturn(false); + String errorMsg = "Message publishing was failed!"; + Throwable exception = new RuntimeException(errorMsg); + given(future.cause()).willReturn(exception); + willAnswer(invocation -> { + GenericFutureListener> listener = invocation.getArgument(0); + listener.operationComplete(future); + return null; + }).given(future).addListener(any()); + + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, "\"string\""); + mqttNode.onMsg(ctxMock, msg); + + then(ctxMock).should(never()).ack(msg); + String expectedData = JacksonUtil.toPlainText(msg.getData()); + then(mqttClientMock).should().publish(mqttNodeConfig.getTopicPattern(), Unpooled.wrappedBuffer(expectedData.getBytes(StandardCharsets.UTF_8)), MqttQoS.AT_LEAST_ONCE, false); + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("error", RuntimeException.class + ": " + errorMsg); + TbMsg expectedMsg = TbMsg.transformMsgMetadata(msg, metaData); + ArgumentCaptor actualMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); + then(ctxMock).should().tellFailure(actualMsgCaptor.capture(), eq(exception)); + TbMsg actualMsg = actualMsgCaptor.getValue(); + assertThat(actualMsg).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(expectedMsg); + } + + @Test + public void givenMqttClientIsNotNull_whenDestroy_thenDisconnect() { + ReflectionTestUtils.setField(mqttNode, "mqttClient", mqttClientMock); + mqttNode.destroy(); + then(mqttClientMock).should().disconnect(); + } + + @Test + public void givenMqttClientIsNull_whenDestroy_thenShouldHaveNoInteractions() { + ReflectionTestUtils.setField(mqttNode, "mqttClient", null); + mqttNode.destroy(); + then(mqttClientMock).shouldHaveNoInteractions(); } private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { @@ -55,6 +333,21 @@ class TbMqttNodeTest extends AbstractRuleNodeUpgradeTest { @Override protected TbNode getTestNode() { - return node; + return mqttNode; + } + + private void mockConnectClient() { + given(ctxMock.getTenantId()).willReturn(TENANT_ID); + given(ctxMock.getSelf()).willReturn(new RuleNode(RULE_NODE_ID)); + given(ctxMock.getSharedEventLoop()).willReturn(eventLoopGroupMock); + willReturn(mqttClientMock).given(mqttNode).getMqttClient(any(), any()); + given(mqttClientMock.connect(any(), anyInt())).willReturn(promiseMock); } + + private void mockSuccessfulInit() throws Exception { + mockConnectClient(); + given(promiseMock.get(anyLong(), any(TimeUnit.class))).willReturn(resultMock); + given(resultMock.isSuccess()).willReturn(true); + } + } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeTest.java new file mode 100644 index 0000000000..819260b35a --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeTest.java @@ -0,0 +1,108 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.mqtt.azure; + +import io.netty.handler.codec.mqtt.MqttVersion; +import org.junit.jupiter.api.BeforeEach; +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.common.util.AzureIotHubUtil; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.mqtt.MqttClient; +import org.thingsboard.mqtt.MqttClientConfig; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.credentials.CertPemCredentials; +import org.thingsboard.rule.engine.mqtt.TbMqttNodeConfiguration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.spy; +import static org.mockito.BDDMockito.willReturn; + +@ExtendWith(MockitoExtension.class) +public class TbAzureIotHubNodeTest { + + private TbAzureIotHubNode azureIotHubNode; + private TbAzureIotHubNodeConfiguration azureIotHubNodeConfig; + + @Mock + protected TbContext ctxMock; + @Mock + protected MqttClient mqttClientMock; + + @BeforeEach + public void setUp() { + azureIotHubNode = spy(new TbAzureIotHubNode()); + azureIotHubNodeConfig = new TbAzureIotHubNodeConfiguration().defaultConfiguration(); + } + + @Test + public void verifyDefaultConfig() { + assertThat(azureIotHubNodeConfig.getTopicPattern()).isEqualTo("devices//messages/events/"); + assertThat(azureIotHubNodeConfig.getHost()).isEqualTo(".azure-devices.net"); + assertThat(azureIotHubNodeConfig.getPort()).isEqualTo(8883); + assertThat(azureIotHubNodeConfig.getConnectTimeoutSec()).isEqualTo(10); + assertThat(azureIotHubNodeConfig.getClientId()).isNull(); + assertThat(azureIotHubNodeConfig.isAppendClientIdSuffix()).isFalse(); + assertThat(azureIotHubNodeConfig.isRetainedMessage()).isFalse(); + assertThat(azureIotHubNodeConfig.isCleanSession()).isTrue(); + assertThat(azureIotHubNodeConfig.isSsl()).isTrue(); + assertThat(azureIotHubNodeConfig.isParseToPlainText()).isFalse(); + assertThat(azureIotHubNodeConfig.getCredentials()).isInstanceOf(AzureIotHubSasCredentials.class); + } + + @Test + public void verifyPrepareMqttClientConfigMethodWithAzureIotHubSasCredentials() throws Exception { + AzureIotHubSasCredentials credentials = new AzureIotHubSasCredentials(); + credentials.setSasKey("testSasKey"); + credentials.setCaCert("test-ca-cert.pem"); + azureIotHubNodeConfig.setCredentials(credentials); + + willReturn(mqttClientMock).given(azureIotHubNode).initAzureClient(any()); + azureIotHubNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(azureIotHubNodeConfig))); + + MqttClientConfig mqttClientConfig = new MqttClientConfig(); + azureIotHubNode.prepareMqttClientConfig(mqttClientConfig); + + assertThat(mqttClientConfig.getProtocolVersion()).isEqualTo(MqttVersion.MQTT_3_1_1); + assertThat(mqttClientConfig.getUsername()).isEqualTo(AzureIotHubUtil.buildUsername(azureIotHubNodeConfig.getHost(), mqttClientConfig.getClientId())); + assertThat(mqttClientConfig.getPassword()).isEqualTo(AzureIotHubUtil.buildSasToken(azureIotHubNodeConfig.getHost(), credentials.getSasKey())); + } + + @Test + public void givenPemCredentialsAndSuccessfulConnectResult_whenInit_thenOk() throws Exception { + CertPemCredentials credentials = new CertPemCredentials(); + credentials.setCaCert("test-ca-cert.pem"); + credentials.setPassword("test-password"); + azureIotHubNodeConfig.setCredentials(credentials); + + willReturn(mqttClientMock).given(azureIotHubNode).initAzureClient(any()); + + assertThatNoException().isThrownBy( + () -> azureIotHubNode.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(azureIotHubNodeConfig)))); + + var mqttNodeConfiguration = (TbMqttNodeConfiguration) ReflectionTestUtils.getField(azureIotHubNode, "mqttNodeConfiguration"); + assertThat(mqttNodeConfiguration).isNotNull(); + assertThat(mqttNodeConfiguration.getPort()).isEqualTo(8883); + assertThat(mqttNodeConfiguration.isCleanSession()).isTrue(); + } + +} 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 19eabf0bdc..04371c23a0 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 @@ -20,13 +20,17 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.provider.Arguments; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.rule.engine.AbstractRuleNodeUpgradeTest; import org.thingsboard.rule.engine.api.RuleEngineAlarmService; import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache; 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; @@ -80,6 +84,7 @@ import java.util.Optional; import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -87,8 +92,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -public class TbDeviceProfileNodeTest { +public class TbDeviceProfileNodeTest extends AbstractRuleNodeUpgradeTest { + @Spy private TbDeviceProfileNode node; @Mock @@ -1723,4 +1729,35 @@ public class TbDeviceProfileNodeTest { }); } + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { + return Stream.of( + // default config for version 1 with upgrade from version 0 + Arguments.of(0, + "{\"persistAlarmRulesState\":false,\"fetchAlarmRulesStateOnStart\":false}", + true, + "{\"persistAlarmRulesState\":false,\"fetchAlarmRulesStateOnStart\":false}"), + // config for version 1 with upgrade from version 0 (persistAlarmRulesState and fetchAlarmRulesStateOnStart - true) + Arguments.of(0, + "{\"persistAlarmRulesState\":true,\"fetchAlarmRulesStateOnStart\":true}", + false, + "{\"persistAlarmRulesState\":true,\"fetchAlarmRulesStateOnStart\":true}"), + // config for version 1 with upgrade from version 0 (persistAlarmRulesState - true, fetchAlarmRulesStateOnStart - false) + Arguments.of(0, + "{\"persistAlarmRulesState\":true,\"fetchAlarmRulesStateOnStart\":false}", + false, + "{\"persistAlarmRulesState\":true,\"fetchAlarmRulesStateOnStart\":false}"), + // config for version 1 with upgrade from version 0 (persistAlarmRulesState - false, fetchAlarmRulesStateOnStart - true) + Arguments.of(0, + "{\"persistAlarmRulesState\":false,\"fetchAlarmRulesStateOnStart\":true}", + true, + "{\"persistAlarmRulesState\":false,\"fetchAlarmRulesStateOnStart\":false}") + ); + + } + + @Override + protected TbNode getTestNode() { + return node; + } + } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNodeTest.java new file mode 100644 index 0000000000..8ce71f684c --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNodeTest.java @@ -0,0 +1,266 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.rabbitmq; + + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.MessageProperties; +import org.junit.jupiter.api.BeforeEach; +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.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +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.common.util.ListeningExecutor; +import org.thingsboard.rule.engine.TestDbCallbackExecutor; +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.api.util.TbNodeUtils; +import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.data.msg.TbNodeConnectionType; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; + +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.given; +import static org.mockito.BDDMockito.mock; +import static org.mockito.BDDMockito.never; +import static org.mockito.BDDMockito.spy; +import static org.mockito.BDDMockito.then; +import static org.mockito.BDDMockito.times; +import static org.mockito.BDDMockito.willAnswer; +import static org.mockito.BDDMockito.willReturn; + +@ExtendWith(MockitoExtension.class) +public class TbRabbitMqNodeTest { + + private final String supportedPropertiesStr = String.join(", ", + "BASIC", "TEXT_PLAIN", "MINIMAL_BASIC", "MINIMAL_PERSISTENT_BASIC", "PERSISTENT_BASIC", "PERSISTENT_TEXT_PLAIN" + ); + + private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("b3d6f9dd-15cc-4e61-acc0-13197a090406")); + private final ListeningExecutor executor = new TestDbCallbackExecutor(); + + private TbRabbitMqNode node; + private TbRabbitMqNodeConfiguration config; + + @Mock + private TbContext ctxMock; + @Mock + private ConnectionFactory factoryMock; + @Mock + private Connection connectionMock; + @Mock + private Channel channelMock; + + @BeforeEach + public void setUp() { + node = spy(new TbRabbitMqNode()); + config = new TbRabbitMqNodeConfiguration().defaultConfiguration(); + } + + @Test + public void verifyDefaultConfig() { + assertThat(config.getExchangeNamePattern()).isEqualTo(""); + assertThat(config.getRoutingKeyPattern()).isEqualTo(""); + assertThat(config.getMessageProperties()).isNull(); + assertThat(config.getHost()).isEqualTo(ConnectionFactory.DEFAULT_HOST); + assertThat(config.getPort()).isEqualTo(ConnectionFactory.DEFAULT_AMQP_PORT); + assertThat(config.getVirtualHost()).isEqualTo(ConnectionFactory.DEFAULT_VHOST); + assertThat(config.getUsername()).isEqualTo(ConnectionFactory.DEFAULT_USER); + assertThat(config.getPassword()).isEqualTo(ConnectionFactory.DEFAULT_PASS); + assertThat(config.isAutomaticRecoveryEnabled()).isFalse(); + assertThat(config.getConnectionTimeout()).isEqualTo(ConnectionFactory.DEFAULT_CONNECTION_TIMEOUT); + assertThat(config.getHandshakeTimeout()).isEqualTo(ConnectionFactory.DEFAULT_HANDSHAKE_TIMEOUT); + assertThat(config.getClientProperties()).isEqualTo(Collections.emptyMap()); + } + + @Test + public void verifyGetConnectionFactoryMethod() { + ReflectionTestUtils.setField(node, "config", config); + + ConnectionFactory connectionFactory = node.getConnectionFactory(); + assertThat(connectionFactory).isNotNull(); + assertThat(connectionFactory.getHost()).isEqualTo(config.getHost()); + assertThat(connectionFactory.getPort()).isEqualTo(config.getPort()); + assertThat(connectionFactory.getVirtualHost()).isEqualTo(config.getVirtualHost()); + assertThat(connectionFactory.getUsername()).isEqualTo(config.getUsername()); + assertThat(connectionFactory.getPassword()).isEqualTo(config.getPassword()); + assertThat(connectionFactory.isAutomaticRecoveryEnabled()).isEqualTo(config.isAutomaticRecoveryEnabled()); + assertThat(connectionFactory.getConnectionTimeout()).isEqualTo(config.getConnectionTimeout()); + assertThat(connectionFactory.getHandshakeTimeout()).isEqualTo(config.getHandshakeTimeout()); + Map expectedClientProperties = new ConnectionFactory().getClientProperties(); + expectedClientProperties.putAll(config.getClientProperties()); + assertThat(connectionFactory.getClientProperties()).isEqualTo(expectedClientProperties); + } + + @ParameterizedTest + @MethodSource + public void givenForceAckIsTrueAndExchangeNameAndRoutingKeyPatternsAndBasicProperties_whenOnMsg_thenPublishMsgAndEnqueueForTellNext( + String exchangeNamePattern, String routingKeyPattern, String basicProperties, TbMsgMetaData metaData, String data + ) throws Exception { + config.setExchangeNamePattern(exchangeNamePattern); + config.setRoutingKeyPattern(routingKeyPattern); + config.setMessageProperties(basicProperties); + + given(ctxMock.isExternalNodeForceAck()).willReturn(true); + mockOnInit(); + given(ctxMock.getExternalCallExecutor()).willReturn(executor); + + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, data); + node.onMsg(ctxMock, msg); + + then(ctxMock).should().ack(msg); + String exchangeName = TbNodeUtils.processPattern(exchangeNamePattern, msg); + String routingKey = TbNodeUtils.processPattern(routingKeyPattern, msg); + AMQP.BasicProperties properties = StringUtils.isNotEmpty(basicProperties) ? TbRabbitMqNode.convert(basicProperties) : null; + then(channelMock).should().basicPublish(exchangeName, routingKey, properties, data.getBytes(StandardCharsets.UTF_8)); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + then(ctxMock).should().enqueueForTellNext(actualMsg.capture(), eq(TbNodeConnectionType.SUCCESS)); + assertThat(actualMsg.getValue()).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(msg); + } + + private static Stream givenForceAckIsTrueAndExchangeNameAndRoutingKeyPatternsAndBasicProperties_whenOnMsg_thenPublishMsgAndEnqueueForTellNext() { + return Stream.of( + Arguments.of("topic_logs", "kern.critical", "", TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT), + Arguments.of("${mdExchangeName}", "${mdRoutingKey}", "BASIC", + new TbMsgMetaData(Map.of("mdExchangeName", "md_topic_logs", "mdRoutingKey", "md.kern.critical")), + TbMsg.EMPTY_JSON_OBJECT), + Arguments.of("$[msgExchangeName]", "$[msgRoutingKey]", "MINIMAL_PERSISTENT_BASIC", + TbMsgMetaData.EMPTY, "{\"msgExchangeName\":\"msg_topic_logs\",\"msgRoutingKey\":\"msg.kern.critical\"}") + ); + } + + @Test + public void givenForceAckIsFalseAndExchangeNameAndRoutingKeyPatternsAndBasicProperties_whenOnMsg_thenPublishMsgAndTellSuccess() throws Exception { + given(ctxMock.isExternalNodeForceAck()).willReturn(false); + mockOnInit(); + given(ctxMock.getExternalCallExecutor()).willReturn(executor); + + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + then(ctxMock).should(never()).ack(any(TbMsg.class)); + then(channelMock).should().basicPublish("", "", null, msg.getData().getBytes(StandardCharsets.UTF_8)); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + then(ctxMock).should().tellSuccess(actualMsg.capture()); + assertThat(actualMsg.getValue()).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(msg); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void givenForceAckAndErrorOccursDuringPublishing_whenOnMsg_thenVerifyTellFailure(boolean forceAck) throws Exception { + given(ctxMock.isExternalNodeForceAck()).willReturn(forceAck); + mockOnInit(); + ListeningExecutor listeningExecutor = mock(ListeningExecutor.class); + given(ctxMock.getExternalCallExecutor()).willReturn(listeningExecutor); + String errorMsg = "Something went wrong"; + ListenableFuture failedFuture = Futures.immediateFailedFuture(new RuntimeException(errorMsg)); + willReturn(failedFuture).given(listeningExecutor).executeAsync(any(Callable.class)); + + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + TbMsgMetaData metaData = new TbMsgMetaData(); + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, TbMsg.EMPTY_JSON_OBJECT); + node.onMsg(ctxMock, msg); + + then(ctxMock).should(forceAck ? times(1) : never()).ack(any(TbMsg.class)); + ArgumentCaptor actualMsg = ArgumentCaptor.forClass(TbMsg.class); + ArgumentCaptor throwable = ArgumentCaptor.forClass(Throwable.class); + Runnable verifyTellFailure = forceAck ? + () -> then(ctxMock).should().enqueueForTellFailure(actualMsg.capture(), throwable.capture()) : + () -> then(ctxMock).should().tellFailure(actualMsg.capture(), throwable.capture()); + verifyTellFailure.run(); + metaData.putValue("error", RuntimeException.class + ": " + errorMsg); + TbMsg expectedMsg = TbMsg.transformMsgMetadata(msg, metaData); + assertThat(actualMsg.getValue()).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(expectedMsg); + assertThat(throwable.getValue()).isInstanceOf(RuntimeException.class).hasMessage(errorMsg); + } + + @ParameterizedTest + @MethodSource + public void givenAMQPBasicPropertiesName_whenConvert_thenReturnAMQPBasicProperties(String name, AMQP.BasicProperties expectedBasicProperties) throws TbNodeException { + AMQP.BasicProperties actualBasicProperties = TbRabbitMqNode.convert(name); + assertThat(actualBasicProperties).isEqualTo(expectedBasicProperties); + } + + private static Stream givenAMQPBasicPropertiesName_whenConvert_thenReturnAMQPBasicProperties() { + return Stream.of( + Arguments.of("BASIC", MessageProperties.BASIC), + Arguments.of("TEXT_PLAIN", MessageProperties.TEXT_PLAIN), + Arguments.of("MINIMAL_BASIC", MessageProperties.MINIMAL_BASIC), + Arguments.of("MINIMAL_PERSISTENT_BASIC", MessageProperties.MINIMAL_PERSISTENT_BASIC), + Arguments.of("PERSISTENT_BASIC", MessageProperties.PERSISTENT_BASIC), + Arguments.of("PERSISTENT_TEXT_PLAIN", MessageProperties.PERSISTENT_TEXT_PLAIN) + ); + } + + @ParameterizedTest + @ValueSource(strings = {"Basic", "TEXT_plain", "minimal basic", "", " "}) + public void givenUndefinedProperties_whenConvert_thenThrowsException(String name) { + assertThatThrownBy(() -> TbRabbitMqNode.convert(name)) + .isInstanceOf(TbNodeException.class) + .hasMessage("Undefined message properties type '" + name + + "'! Only " + supportedPropertiesStr + " message properties types are supported!"); + } + + @Test + public void givenConnection_whenDestroy_thenShouldClose() throws IOException { + ReflectionTestUtils.setField(node, "connection", connectionMock); + node.destroy(); + then(connectionMock).should().close(); + } + + @Test + public void givenConnectionIsNull_whenDestroy_thenVerifyNoInteractions() { + node.destroy(); + then(connectionMock).shouldHaveNoInteractions(); + } + + private void mockOnInit() throws IOException, TimeoutException { + willAnswer(invocation -> factoryMock).given(node).getConnectionFactory(); + given(factoryMock.newConnection()).willReturn(connectionMock); + given(connectionMock.createChannel()).willReturn(channelMock); + } + +} diff --git a/ui-ngx/src/app/core/core.module.ts b/ui-ngx/src/app/core/core.module.ts index 032197057e..4b3fb44b12 100644 --- a/ui-ngx/src/app/core/core.module.ts +++ b/ui-ngx/src/app/core/core.module.ts @@ -41,6 +41,7 @@ import { WINDOW_PROVIDERS } from '@core/services/window.service'; import { HotkeyModule } from 'angular2-hotkeys'; import { TranslateDefaultParser } from '@core/translate/translate-default-parser'; import { TranslateDefaultLoader } from '@core/translate/translate-default-loader'; +import { EntityConflictInterceptor } from '@core/interceptors/entity-conflict.interceptor'; @NgModule({ imports: [ @@ -95,6 +96,11 @@ import { TranslateDefaultLoader } from '@core/translate/translate-default-loader useClass: GlobalHttpInterceptor, multi: true }, + { + provide: HTTP_INTERCEPTORS, + useClass: EntityConflictInterceptor, + multi: true + }, { provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { diff --git a/ui-ngx/src/app/core/interceptors/entity-conflict.interceptor.ts b/ui-ngx/src/app/core/interceptors/entity-conflict.interceptor.ts new file mode 100644 index 0000000000..57ee28c779 --- /dev/null +++ b/ui-ngx/src/app/core/interceptors/entity-conflict.interceptor.ts @@ -0,0 +1,90 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT 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 { Injectable } from '@angular/core'; +import { + HttpErrorResponse, + HttpEvent, + HttpHandler, + HttpInterceptor, + HttpRequest, + HttpStatusCode +} from '@angular/common/http'; +import { Observable, of, throwError } from 'rxjs'; +import { catchError, switchMap } from 'rxjs/operators'; +import { MatDialog } from '@angular/material/dialog'; +import { + EntityConflictDialogComponent +} from '@shared/components/dialog/entity-conflict-dialog/entity-conflict-dialog.component'; +import { HasId } from '@shared/models/base-data'; +import { HasVersion } from '@shared/models/entity.models'; +import { getInterceptorConfig } from './interceptor.util'; + +@Injectable() +export class EntityConflictInterceptor implements HttpInterceptor { + + constructor( + private dialog: MatDialog, + ) {} + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + if (!request.url.startsWith('/api/')) { + return next.handle(request); + } + + return next.handle(request).pipe( + catchError((error: HttpErrorResponse) => { + if (error.status !== HttpStatusCode.Conflict) { + return throwError(() => error); + } + + return this.handleConflictError(request, next, error); + }) + ); + } + + private handleConflictError( + request: HttpRequest, + next: HttpHandler, + error: HttpErrorResponse + ): Observable> { + if (getInterceptorConfig(request).ignoreVersionConflict) { + return throwError(() => error); + } + + return this.openConflictDialog(request.body, error.error.message).pipe( + switchMap(result => { + if (result) { + return next.handle(this.updateRequestVersion(request)); + } + return of(null); + }) + ); + } + + private updateRequestVersion(request: HttpRequest): HttpRequest { + const body = { ...request.body, version: null }; + return request.clone({ body }); + } + + private openConflictDialog(entity: unknown & HasId & HasVersion, message: string): Observable { + const dialogRef = this.dialog.open(EntityConflictDialogComponent, { + data: { message, entity } + }); + + return dialogRef.afterClosed(); + } +} diff --git a/ui-ngx/src/app/core/interceptors/global-http-interceptor.ts b/ui-ngx/src/app/core/interceptors/global-http-interceptor.ts index 502df634f3..1cdd0c506e 100644 --- a/ui-ngx/src/app/core/interceptors/global-http-interceptor.ts +++ b/ui-ngx/src/app/core/interceptors/global-http-interceptor.ts @@ -16,10 +16,9 @@ import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs/internal/Observable'; -import { Inject, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; import { AuthService } from '@core/auth/auth.service'; import { Constants } from '@shared/models/constants'; -import { InterceptorHttpParams } from './interceptor-http-params'; import { catchError, delay, finalize, mergeMap, switchMap } from 'rxjs/operators'; import { of, throwError } from 'rxjs'; import { InterceptorConfig } from './interceptor-config'; @@ -30,6 +29,7 @@ import { ActionNotificationShow } from '@app/core/notification/notification.acti import { DialogService } from '@core/services/dialog.service'; import { TranslateService } from '@ngx-translate/core'; import { parseHttpErrorMessage } from '@core/utils'; +import { getInterceptorConfig } from './interceptor.util'; const tmpHeaders = {}; @@ -39,22 +39,18 @@ export class GlobalHttpInterceptor implements HttpInterceptor { private AUTH_SCHEME = 'Bearer '; private AUTH_HEADER_NAME = 'X-Authorization'; - private internalUrlPrefixes = [ - '/api/auth/token', - '/api/rpc' - ]; - private activeRequests = 0; - constructor(@Inject(Store) private store: Store, - @Inject(DialogService) private dialogService: DialogService, - @Inject(TranslateService) private translate: TranslateService, - @Inject(AuthService) private authService: AuthService) { - } + constructor( + private store: Store, + private dialogService: DialogService, + private translate: TranslateService, + private authService: AuthService, + ) {} intercept(req: HttpRequest, next: HttpHandler): Observable> { if (req.url.startsWith('/api/')) { - const config = this.getInterceptorConfig(req); + const config = getInterceptorConfig(req); this.updateLoadingState(config, true); let observable$: Observable>; if (this.isTokenBasedAuthEntryPoint(req.url)) { @@ -98,7 +94,7 @@ export class GlobalHttpInterceptor implements HttpInterceptor { } private handleResponseError(req: HttpRequest, next: HttpHandler, errorResponse: HttpErrorResponse): Observable> { - const config = this.getInterceptorConfig(req); + const config = getInterceptorConfig(req); let unhandled = false; const ignoreErrors = config.ignoreErrors; const resendRequest = config.resendRequest; @@ -171,15 +167,6 @@ export class GlobalHttpInterceptor implements HttpInterceptor { } } - private isInternalUrlPrefix(url: string): boolean { - for (const index in this.internalUrlPrefixes) { - if (url.startsWith(this.internalUrlPrefixes[index])) { - return true; - } - } - return false; - } - private isTokenBasedAuthEntryPoint(url: string): boolean { return url.startsWith('/api/') && !url.startsWith(Constants.entryPoints.login) && @@ -202,19 +189,6 @@ export class GlobalHttpInterceptor implements HttpInterceptor { } } - private getInterceptorConfig(req: HttpRequest): InterceptorConfig { - let config: InterceptorConfig; - if (req.params && req.params instanceof InterceptorHttpParams) { - config = (req.params as InterceptorHttpParams).interceptorConfig; - } else { - config = new InterceptorConfig(false, false); - } - if (this.isInternalUrlPrefix(req.url)) { - config.ignoreLoading = true; - } - return config; - } - private showError(error: string, timeout: number = 0) { setTimeout(() => { this.store.dispatch(new ActionNotificationShow({message: error, type: 'error'})); diff --git a/ui-ngx/src/app/core/interceptors/interceptor-config.ts b/ui-ngx/src/app/core/interceptors/interceptor-config.ts index 5a83d34c6b..62500cbefc 100644 --- a/ui-ngx/src/app/core/interceptors/interceptor-config.ts +++ b/ui-ngx/src/app/core/interceptors/interceptor-config.ts @@ -17,5 +17,6 @@ export class InterceptorConfig { constructor(public ignoreLoading: boolean = false, public ignoreErrors: boolean = false, + public ignoreVersionConflict: boolean = false, public resendRequest: boolean = false) {} } diff --git a/ui-ngx/src/app/core/interceptors/interceptor.util.ts b/ui-ngx/src/app/core/interceptors/interceptor.util.ts new file mode 100644 index 0000000000..ed9fc41868 --- /dev/null +++ b/ui-ngx/src/app/core/interceptors/interceptor.util.ts @@ -0,0 +1,46 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { HttpRequest } from '@angular/common/http'; +import { InterceptorConfig } from '@core/interceptors/interceptor-config'; +import { InterceptorHttpParams } from '@core/interceptors/interceptor-http-params'; + +const internalUrlPrefixes = [ + '/api/auth/token', + '/api/rpc' +]; + +export const getInterceptorConfig = (req: HttpRequest): InterceptorConfig => { + let config: InterceptorConfig; + if (req.params && req.params instanceof InterceptorHttpParams) { + config = (req.params as InterceptorHttpParams).interceptorConfig; + } else { + config = new InterceptorConfig(); + } + if (isInternalUrlPrefix(req.url)) { + config.ignoreLoading = true; + } + return config; +}; + +const isInternalUrlPrefix = (url: string): boolean => { + for (const prefix of internalUrlPrefixes) { + if (url.startsWith(prefix)) { + return true; + } + } + return false; +}; diff --git a/ui-ngx/src/app/core/services/mobile.service.ts b/ui-ngx/src/app/core/services/mobile.service.ts index 03772ce167..7b11b817b4 100644 --- a/ui-ngx/src/app/core/services/mobile.service.ts +++ b/ui-ngx/src/app/core/services/mobile.service.ts @@ -30,6 +30,7 @@ const dashboardLoadedHandler = 'tbMobileDashboardLoadedHandler'; const dashboardLayoutHandler = 'tbMobileDashboardLayoutHandler'; const navigationHandler = 'tbMobileNavigationHandler'; const mobileHandler = 'tbMobileHandler'; +const mobileReadyHandler = 'tbMobileReadyHandler'; // @dynamic @Injectable({ @@ -54,6 +55,7 @@ export class MobileService { this.mobileApp = isDefined(this.mobileChannel); if (this.mobileApp) { window.addEventListener('message', this.onWindowMessageListener); + this.mobileChannel.callHandler(mobileReadyHandler); } } diff --git a/ui-ngx/src/app/modules/common/modules-map.ts b/ui-ngx/src/app/modules/common/modules-map.ts index fcb4e0b411..c06863c6e8 100644 --- a/ui-ngx/src/app/modules/common/modules-map.ts +++ b/ui-ngx/src/app/modules/common/modules-map.ts @@ -99,6 +99,9 @@ import * as TbJsonPipe from '@shared/pipe/tbJson.pipe'; import * as TruncatePipe from '@shared/pipe/truncate.pipe'; import * as ImagePipe from '@shared/pipe/image.pipe'; +import * as EllipsisChipListDirective from '@shared/directives/ellipsis-chip-list.directive'; +import * as TruncateWithTooltipDirective from '@shared/directives/truncate-with-tooltip.directive'; + import * as coercion from '@shared/decorators/coercion'; import * as enumerable from '@shared/decorators/enumerable'; import * as TbInject from '@shared/decorators/tb-inject'; @@ -422,6 +425,9 @@ class ModulesMap implements IModulesMap { '@shared/pipe/truncate.pipe': TruncatePipe, '@shared/pipe/image.pipe': ImagePipe, + '@shared/directives/ellipsis-chip-list.directive': EllipsisChipListDirective, + '@shared/directives/truncate-with-tooltip.directive': TruncateWithTooltipDirective, + '@shared/decorators/coercion': coercion, '@shared/decorators/enumerable': enumerable, '@shared/decorators/tb-inject': TbInject, diff --git a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-table-config.ts b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-table-config.ts index b5c94f9aeb..fa4e8bcc71 100644 --- a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-table-config.ts @@ -20,12 +20,19 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; import { + ActionStatus, actionStatusTranslations, + ActionType, actionTypeTranslations, AuditLog, AuditLogMode } from '@shared/models/audit-log.models'; -import { EntityTypeResource, entityTypeTranslations } from '@shared/models/entity-type.models'; +import { + AliasEntityType, + EntityType, + EntityTypeResource, + entityTypeTranslations +} from '@shared/models/entity-type.models'; import { AuditLogService } from '@core/http/audit-log.service'; import { TranslateService } from '@ngx-translate/core'; import { DatePipe } from '@angular/common'; @@ -82,7 +89,7 @@ export class AuditLogTableConfig extends EntityTableConfig('entityType', 'audit-log.entity-type', '20%', - (entity) => translate.instant(entityTypeTranslations.get(entity.entityId.entityType).type)), + (entity) => this.getEntityTypeTranslation(entity.entityId.entityType)), new EntityTableColumn('entityName', 'audit-log.entity-name', '20%'), ); } @@ -95,9 +102,9 @@ export class AuditLogTableConfig extends EntityTableConfig('actionType', 'audit-log.type', '33%', - (entity) => translate.instant(actionTypeTranslations.get(entity.actionType))), + (entity) => this.getActionTypeTranslation(entity.actionType)), new EntityTableColumn('actionStatus', 'audit-log.status', '33%', - (entity) => translate.instant(actionStatusTranslations.get(entity.actionStatus))) + (entity) => this.getActionStatusTranslation(entity.actionStatus)) ); this.cellActionDescriptors.push( @@ -105,11 +112,32 @@ export class AuditLogTableConfig extends EntityTableConfig true, - onAction: ($event, entity) => this.showAuditLogDetails(entity) + onAction: (_, entity) => this.showAuditLogDetails(entity) } ); } + private getEntityTypeTranslation(entityType: EntityType | AliasEntityType): string { + if (entityTypeTranslations.has(entityType) && entityTypeTranslations.get(entityType).type) { + return this.translate.instant(entityTypeTranslations.get(entityType).type); + } + return entityType; + } + + private getActionTypeTranslation(actionType: ActionType): string { + if (actionTypeTranslations.has(actionType)) { + return this.translate.instant(actionTypeTranslations.get(actionType)); + } + return actionType; + } + + private getActionStatusTranslation(actionStatus: ActionStatus): string { + if (actionStatusTranslations.has(actionStatus)) { + return this.translate.instant(actionStatusTranslations.get(actionStatus)); + } + return actionStatus; + } + fetchAuditLogs(pageLink: TimePageLink): Observable> { switch (this.auditLogMode) { case AuditLogMode.TENANT: diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.html index c7f8980426..8baaa67ead 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.html @@ -44,6 +44,7 @@ [dashboard]="dashboard" [widget]="widget" [hideHeader]="hideHeader" + [scada]="data.scada" isAdd formControlName="widgetConfig"> 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 2089c03d5d..662739295b 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 @@ -37,6 +37,7 @@ export interface AddWidgetDialogData { stateController: IStateController; widget: Widget; widgetInfo: WidgetInfo; + scada: boolean; } @Component({ diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html index e69be1e684..49f2cf9ac3 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html @@ -385,6 +385,7 @@ [widgetEditMode]="widgetEditMode" [widget]="editingWidget" [widgetLayout]="editingWidgetLayout" + [scada]="editingLayoutCtx?.gridSettings?.layoutType === LayoutType.scada" (revertWidgetConfig)="onRevertWidgetEdit()" (applyWidgetConfig)="saveWidget()"> 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 9b6471e3d2..c7549122b8 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 @@ -1327,7 +1327,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC col: 0 }; newWidget = this.dashboardUtils.validateAndUpdateWidget(newWidget); - if (this.isAddingToScadaLayout()) { + const scada = this.isAddingToScadaLayout(); + if (scada) { newWidget = this.dashboardUtils.prepareWidgetForScadaLayout(newWidget); } if (widgetTypeInfo.typeParameters.useCustomDatasources) { @@ -1344,7 +1345,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC aliasController: this.dashboardCtx.aliasController, stateController: this.dashboardCtx.stateController, widget: newWidget, - widgetInfo: widgetTypeInfo + widgetInfo: widgetTypeInfo, + scada } }).afterClosed().subscribe((addedWidget) => { if (addedWidget) { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html index 8c21279f5c..ceeb91d084 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html @@ -24,6 +24,7 @@ [dashboard]="dashboard" [widget]="widget" [hideToggleHeader]="previewMode" + [scada]="scada" formControlName="widgetConfig">
-
widget-config.appearance
+
widget-config.card-appearance
{{ 'widgets.background.background' | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts index f7d37b167e..d4bfdd4694 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts @@ -109,12 +109,13 @@ export class BrokerConfigControlComponent implements ControlValueAccessor, Valid } writeValue(brokerConfig: BrokerConfig): void { - const brokerConfigState = { - ...brokerConfig, - version: brokerConfig.version || 5, - clientId: brokerConfig.clientId || 'tb_gw_' + generateSecret(5), - }; - this.brokerConfigFormGroup.reset(brokerConfigState, {emitEvent: false}); + const { + version = 5, + clientId = `tb_gw_${generateSecret(5)}`, + security = {}, + } = brokerConfig; + + this.brokerConfigFormGroup.reset({ ...brokerConfig, version, clientId, security }, { emitEvent: false }); this.cdr.markForCheck(); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html index 9f0566b566..7e1ab2bb62 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html @@ -18,7 +18,7 @@
-
+
{{mappingTypeTranslationsMap.get(mappingType) | translate}}
@@ -75,15 +75,22 @@ -
+ + +
+
- - +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html index 17f5185bc6..30233cddcf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html @@ -19,10 +19,20 @@ - + +
+
{{ 'gateway.hints.modbus-server' | translate }}
+
+ + + {{ 'gateway.enable' | translate }} + + +
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.scss index b70fe42401..3b7e7288c8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.scss @@ -16,9 +16,3 @@ :host { height: 100%; } - -:host ::ng-deep { - .mat-mdc-tab-body-content { - overflow: hidden !important; - } -} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 1fca768980..aa0424da93 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -18,13 +18,15 @@ import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, Templ import { ControlValueAccessor, FormBuilder, + FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, + UntypedFormControl, ValidationErrors, Validator, } from '@angular/forms'; -import { ConnectorType, ModbusBasicConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { ModbusBasicConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { SharedModule } from '@shared/shared.module'; import { CommonModule } from '@angular/common'; import { takeUntil } from 'rxjs/operators'; @@ -33,6 +35,7 @@ import { Subject } from 'rxjs'; import { EllipsisChipListDirective } from '@shared/directives/ellipsis-chip-list.directive'; import { ModbusSlaveConfigComponent } from '../modbus-slave-config/modbus-slave-config.component'; import { ModbusMasterTableComponent } from '../modbus-master-table/modbus-master-table.component'; +import { isEqual } from '@core/utils'; @Component({ selector: 'tb-modbus-basic-config', @@ -66,6 +69,7 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat @Input() generalTabContent: TemplateRef; basicFormGroup: FormGroup; + enableSlaveControl: FormControl; onChange: (value: ModbusBasicConfig) => void; onTouched: () => void; @@ -77,13 +81,21 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat master: [], slave: [], }); + this.enableSlaveControl = new FormControl(false); this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) - .subscribe(value => { - this.onChange(value); + .subscribe(({ master, slave }) => { + this.onChange({ master, slave: slave ?? {} }); this.onTouched(); }); + + this.enableSlaveControl.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(enable => { + this.updateSlaveEnabling(enable); + this.basicFormGroup.get('slave').updateValueAndValidity({emitEvent: !!this.onChange}); + }); } ngOnDestroy(): void { @@ -106,11 +118,25 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat }; this.basicFormGroup.setValue(editedBase, {emitEvent: false}); + this.enableSlaveControl.setValue(!!basicConfig.slave && !isEqual(basicConfig.slave, {})); } - validate(): ValidationErrors | null { - return this.basicFormGroup.valid ? null : { - basicFormGroup: {valid: false} - }; + validate(basicFormControl: UntypedFormControl): ValidationErrors | null { + const { master, slave } = basicFormControl.value; + const isEmpty = !master?.slaves?.length && (isEqual(slave, {}) || !slave); + if (!this.basicFormGroup.valid || isEmpty) { + return { + basicFormGroup: {valid: false} + }; + } + return null; + } + + private updateSlaveEnabling(isEnabled: boolean): void { + if (isEnabled) { + this.basicFormGroup.get('slave').enable({emitEvent: false}); + } else { + this.basicFormGroup.get('slave').disable({emitEvent: false}); + } } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html index 02d2d1491d..cfb97f674d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html @@ -26,19 +26,32 @@ -
- - {{ keyControl.get('tag').value }}{{ '-' }}{{ keyControl.get('value').value }} - - {{ keyControl.get('tag').value }} +
+ {{ keyControl.get('tag').value }}{{ '-' }}{{ keyControl.get('value').value }}
+ +
+
{{ 'gateway.key' | translate }}: {{ keyControl.get('tag').value }}
+
{{ 'gateway.address' | translate }}: {{ keyControl.get('address').value }}
+
{{ 'gateway.type' | translate }}: {{ keyControl.get('type').value }}
+
+
+
+ {{ 'gateway.hints.modbus.data-keys' | translate }} +
+
+
gateway.platform-side
-
+
gateway.key
@@ -87,7 +100,7 @@
-
gateway.objects-count
+
gateway.objects-count
+ + warning +
-
gateway.address
+
gateway.address
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss index 0e9f9a432f..445ac6c0ae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss @@ -20,10 +20,7 @@ max-width: 700px; .title-container { - max-width: 11vw; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap + width: 180px; } .key-panel { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts index 5b312f52c8..93ca232e38 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts @@ -27,6 +27,7 @@ import { import { TbPopoverComponent } from '@shared/components/popover.component'; import { ModbusDataType, + ModbusEditableDataTypes, ModbusFunctionCodeTranslationsMap, ModbusObjectCountByDataType, ModbusValue, @@ -40,6 +41,7 @@ import { generateSecret } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; +import { TruncateWithTooltipDirective } from '@shared/directives/truncate-with-tooltip.directive'; @Component({ selector: 'tb-modbus-data-keys-panel', @@ -50,6 +52,7 @@ import { Subject } from 'rxjs'; CommonModule, SharedModule, GatewayHelpLinkPipe, + TruncateWithTooltipDirective, ] }) export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { @@ -72,14 +75,15 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { functionCodesMap = new Map(); defaultFunctionCodes = []; - readonly editableDataTypes = [ModbusDataType.BYTES, ModbusDataType.BITS, ModbusDataType.STRING]; + readonly ModbusEditableDataTypes = ModbusEditableDataTypes; readonly ModbusFunctionCodeTranslationsMap = ModbusFunctionCodeTranslationsMap; private destroy$ = new Subject(); private readonly defaultReadFunctionCodes = [3, 4]; - private readonly defaultWriteFunctionCodes = [5, 6, 15, 16]; - private readonly stringAttrUpdatesWriteFunctionCodes = [6, 16]; + private readonly bitsReadFunctionCodes = [1, 2]; + private readonly defaultWriteFunctionCodes = [6, 16]; + private readonly bitsWriteFunctionCodes = [5, 15]; constructor(private fb: UntypedFormBuilder) {} @@ -161,7 +165,7 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { private observeKeyDataType(keyFormGroup: FormGroup): void { keyFormGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(dataType => { - if (!this.editableDataTypes.includes(dataType)) { + if (!this.ModbusEditableDataTypes.includes(dataType)) { keyFormGroup.get('objectsCount').patchValue(ModbusObjectCountByDataType[dataType], {emitEvent: false}); } this.updateFunctionCodes(keyFormGroup, dataType); @@ -177,23 +181,23 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { } private getFunctionCodes(dataType: ModbusDataType): number[] { + const writeFunctionCodes = [ + ...(dataType === ModbusDataType.BITS ? this.bitsWriteFunctionCodes : []), ...this.defaultWriteFunctionCodes + ]; + if (this.keysType === ModbusValueKey.ATTRIBUTES_UPDATES) { - return dataType === ModbusDataType.STRING - ? this.stringAttrUpdatesWriteFunctionCodes - : this.defaultWriteFunctionCodes; + return writeFunctionCodes.sort((a, b) => a - b); } const functionCodes = [...this.defaultReadFunctionCodes]; if (dataType === ModbusDataType.BITS) { - const bitsFunctionCodes = [1, 2]; - functionCodes.push(...bitsFunctionCodes); - functionCodes.sort(); + functionCodes.push(...this.bitsReadFunctionCodes); } if (this.keysType === ModbusValueKey.RPC_REQUESTS) { - functionCodes.push(...this.defaultWriteFunctionCodes); + functionCodes.push(...writeFunctionCodes); } - return functionCodes; + return functionCodes.sort((a, b) => a - b); } private getDefaultFunctionCodes(): number[] { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html index e16aa0c51f..8f8aeaeef7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html @@ -16,9 +16,12 @@ -->
+
+
{{ 'gateway.hints.modbus-master' | translate }}
+
-
+
{{ 'gateway.servers-slaves' | translate}}
@@ -63,33 +66,40 @@ {{ 'gateway.name' | translate }} - - {{ mapping['name'] }} + + {{ slave['name'] }} {{ 'gateway.client-communication-type' | translate }} - - {{ ModbusProtocolLabelsMap.get(mapping['type']) }} + + {{ ModbusProtocolLabelsMap.get(slave['type']) }} - -
+ + +
+
- - +
- +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 2cb66f6062..4787523b40 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -34,18 +34,17 @@ import { ControlValueAccessor, FormArray, FormBuilder, - NG_VALIDATORS, NG_VALUE_ACCESSOR, UntypedFormGroup, - ValidationErrors, - Validator, } from '@angular/forms'; import { ModbusMasterConfig, ModbusProtocolLabelsMap, + ModbusSlaveInfo, + ModbusValues, SlaveConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { isDefinedAndNotNull, isUndefinedOrNull } from '@core/utils'; +import { isDefinedAndNotNull } from '@core/utils'; import { SharedModule } from '@shared/shared.module'; import { CommonModule } from '@angular/common'; import { ModbusSlaveDialogComponent } from '../modbus-slave-dialog/modbus-slave-dialog.component'; @@ -62,16 +61,11 @@ import { TbTableDatasource } from '@shared/components/table/table-datasource.abs useExisting: forwardRef(() => ModbusMasterTableComponent), multi: true }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ModbusMasterTableComponent), - multi: true - } ], standalone: true, imports: [CommonModule, SharedModule] }) -export class ModbusMasterTableComponent implements ControlValueAccessor, Validator, AfterViewInit, OnInit, OnDestroy { +export class ModbusMasterTableComponent implements ControlValueAccessor, AfterViewInit, OnInit, OnDestroy { @ViewChild('searchInput') searchInputField: ElementRef; @@ -138,12 +132,6 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat this.pushDataAsFormArrays(master.slaves); } - validate(): ValidationErrors | null { - return this.slaves.controls.length ? null : { - slavesFormGroup: {valid: false} - }; - } - enterFilterMode(): void { this.textSearchMode = true; this.cdr.detectChanges(); @@ -164,12 +152,12 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat } const withIndex = isDefinedAndNotNull(index); const value = withIndex ? this.slaves.at(index).value : {}; - this.dialog.open(ModbusSlaveDialogComponent, { + this.dialog.open(ModbusSlaveDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { value, - buttonTitle: withIndex ? 'action.add' : 'action.apply' + buttonTitle: withIndex ? 'action.apply' : 'action.add' } }).afterClosed() .pipe(take(1), takeUntil(this.destroy$)) @@ -185,7 +173,7 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat }); } - deleteMapping($event: Event, index: number): void { + deleteSlave($event: Event, index: number): void { if ($event) { $event.stopPropagation(); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html new file mode 100644 index 0000000000..c2dead1abc --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html @@ -0,0 +1,92 @@ + + +
+ + {{ 'gateway.key' | translate }} + + + warning + + +
+
+ + {{ 'gateway.rpc.type' | translate }} + + {{ type }} + + + + {{ 'gateway.rpc.functionCode' | translate }} + + {{ ModbusFunctionCodeTranslationsMap.get(code) | translate}} + + +
+
+ + {{ 'gateway.rpc.value' | translate }} + + + warning + + +
+
+ + {{ 'gateway.rpc.address' | translate }} + + + warning + + + + {{ 'gateway.rpc.objectsCount' | translate }} + + +
+
+ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts new file mode 100644 index 0000000000..17c48cc595 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts @@ -0,0 +1,166 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { + ChangeDetectionStrategy, + Component, + forwardRef, + OnDestroy, +} from '@angular/core'; +import { + ControlValueAccessor, + FormBuilder, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + UntypedFormGroup, + ValidationErrors, + Validator, + Validators +} from '@angular/forms'; +import { SharedModule } from '@shared/shared.module'; +import { CommonModule } from '@angular/common'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { + ModbusDataType, + ModbusEditableDataTypes, + ModbusFunctionCodeTranslationsMap, + ModbusObjectCountByDataType, + ModbusValue, + noLeadTrailSpacesRegex, +} from '@home/components/widget/lib/gateway/gateway-widget.models'; + +@Component({ + selector: 'tb-modbus-rpc-parameters', + templateUrl: './modbus-rpc-parameters.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ModbusRpcParametersComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ModbusRpcParametersComponent), + multi: true + } + ], + standalone: true, + imports: [ + CommonModule, + SharedModule, + ], +}) +export class ModbusRpcParametersComponent implements ControlValueAccessor, Validator, OnDestroy { + + rpcParametersFormGroup: UntypedFormGroup; + functionCodes: Array; + + readonly ModbusEditableDataTypes = ModbusEditableDataTypes; + readonly ModbusFunctionCodeTranslationsMap = ModbusFunctionCodeTranslationsMap; + + readonly modbusDataTypes = Object.values(ModbusDataType) as ModbusDataType[]; + readonly writeFunctionCodes = [5, 6, 15, 16]; + + private readonly defaultFunctionCodes = [3, 4, 6, 16]; + private readonly readFunctionCodes = [1, 2, 3, 4]; + private readonly bitsFunctionCodes = [...this.readFunctionCodes, ...this.writeFunctionCodes]; + + private onChange: (value: ModbusValue) => void; + private onTouched: () => void; + + private destroy$ = new Subject(); + + constructor(private fb: FormBuilder) { + this.rpcParametersFormGroup = this.fb.group({ + tag: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], + type: [ModbusDataType.BYTES, [Validators.required]], + functionCode: [this.defaultFunctionCodes[0], [Validators.required]], + value: [{value: '', disabled: true}, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], + address: [null, [Validators.required]], + objectsCount: [1, [Validators.required]], + }); + + this.updateFunctionCodes(this.rpcParametersFormGroup.get('type').value); + this.observeValueChanges(); + this.observeKeyDataType(); + this.observeFunctionCode(); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + registerOnChange(fn: (value: ModbusValue) => void): void { + this.onChange = fn; + } + + registerOnTouched(fn: () => void): void { + this.onTouched = fn; + } + + validate(): ValidationErrors | null { + return this.rpcParametersFormGroup.valid ? null : { + rpcParametersFormGroup: { valid: false } + }; + } + + writeValue(value: ModbusValue): void { + this.rpcParametersFormGroup.patchValue(value, {emitEvent: false}); + } + + private observeValueChanges(): void { + this.rpcParametersFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + this.onChange(value); + this.onTouched(); + }); + } + + private observeKeyDataType(): void { + this.rpcParametersFormGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(dataType => { + if (!this.ModbusEditableDataTypes.includes(dataType)) { + this.rpcParametersFormGroup.get('objectsCount').patchValue(ModbusObjectCountByDataType[dataType], {emitEvent: false}); + } + this.updateFunctionCodes(dataType); + }); + } + + private observeFunctionCode(): void { + this.rpcParametersFormGroup.get('functionCode').valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(code => this.updateValueEnabling(code)); + } + + private updateValueEnabling(code: number): void { + if (this.writeFunctionCodes.includes(code)) { + this.rpcParametersFormGroup.get('value').enable({emitEvent: false}); + } else { + this.rpcParametersFormGroup.get('value').setValue(null); + this.rpcParametersFormGroup.get('value').disable({emitEvent: false}); + } + } + + private updateFunctionCodes(dataType: ModbusDataType): void { + this.functionCodes = dataType === ModbusDataType.BITS ? this.bitsFunctionCodes : this.defaultFunctionCodes; + if (!this.functionCodes.includes(this.rpcParametersFormGroup.get('functionCode').value)) { + this.rpcParametersFormGroup.get('functionCode').patchValue(this.functionCodes[0], {emitEvent: false}); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.html index 66db8c5018..3fc3e33ad0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.html @@ -18,7 +18,9 @@
{{ 'gateway.hints.path-in-os' | translate }}
-
gateway.client-cert-path
+
+ gateway.client-cert-path +
@@ -26,7 +28,9 @@
-
gateway.private-key-path
+
+ gateway.private-key-path +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.ts index bc40727b55..062f77fafb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.ts @@ -42,6 +42,7 @@ import { CommonModule } from '@angular/common'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { TruncateWithTooltipDirective } from '@shared/directives/truncate-with-tooltip.directive'; @Component({ selector: 'tb-modbus-security-config', @@ -63,6 +64,7 @@ import { coerceBoolean } from '@shared/decorators/coercion'; imports: [ CommonModule, SharedModule, + TruncateWithTooltipDirective, ] }) export class ModbusSecurityConfigComponent implements ControlValueAccessor, Validator, OnChanges, OnDestroy { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html index d37c8cc9ee..9360ef499a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html @@ -16,16 +16,6 @@ -->
-
-
{{ 'gateway.hints.modbus-server' | translate }}
-
- - - {{ 'gateway.enable' | translate }} - - -
-
gateway.server-slave-config
@@ -38,7 +28,7 @@ class="tb-form-row column-xs" fxLayoutAlign="space-between center" > -
gateway.host
+
gateway.host
@@ -58,7 +48,7 @@ class="tb-form-row column-xs" fxLayoutAlign="space-between center" > -
gateway.port
+
gateway.port
-
gateway.port
+
gateway.port
@@ -96,7 +86,7 @@
-
+
gateway.method
@@ -110,7 +100,7 @@
-
gateway.unit-id
+
gateway.unit-id
@@ -161,7 +151,11 @@
-
gateway.poll-period
+
+ + gateway.poll-period + +
@@ -169,7 +163,7 @@
-
gateway.baudrate
+
gateway.baudrate
@@ -178,6 +172,13 @@
+
+ + + {{ 'gateway.send-data-TB' | translate }} + + +
@@ -187,7 +188,7 @@
-
gateway.byte-order
+
gateway.byte-order
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts index 2a8488a2d4..206b0c2ac5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts @@ -43,11 +43,12 @@ import { import { SharedModule } from '@shared/shared.module'; import { CommonModule } from '@angular/common'; import { Subject } from 'rxjs'; -import { startWith, takeUntil } from 'rxjs/operators'; +import { takeUntil } from 'rxjs/operators'; import { GatewayPortTooltipPipe } from '@home/components/widget/lib/gateway/pipes/gateway-port-tooltip.pipe'; import { ModbusSecurityConfigComponent } from '../modbus-security-config/modbus-security-config.component'; import { ModbusValuesComponent, } from '../modbus-values/modbus-values.component'; import { isEqual } from '@core/utils'; +import { TruncateWithTooltipDirective } from '@shared/directives/truncate-with-tooltip.directive'; @Component({ selector: 'tb-modbus-slave-config', @@ -72,8 +73,8 @@ import { isEqual } from '@core/utils'; ModbusValuesComponent, ModbusSecurityConfigComponent, GatewayPortTooltipPipe, + TruncateWithTooltipDirective, ], - styleUrls: ['./modbus-slave-config.component.scss'], }) export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validator, OnDestroy { @@ -90,6 +91,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat readonly ModbusProtocolType = ModbusProtocolType; readonly modbusBaudrates = ModbusBaudrates; + private isSlaveEnabled = false; private readonly serialSpecificControlKeys = ['serialPort', 'baudrate']; private readonly tcpUdpSpecificControlKeys = ['port', 'security', 'host']; @@ -106,11 +108,11 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat port: [null, [Validators.required, Validators.min(PortLimits.MIN), Validators.max(PortLimits.MAX)]], serialPort: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], method: [ModbusMethodType.SOCKET], - unitId: [0, [Validators.required]], + unitId: [null, [Validators.required]], baudrate: [this.modbusBaudrates[0]], deviceName: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], deviceType: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], - pollPeriod: [5000], + pollPeriod: [5000, [Validators.required]], sendDataToThingsBoard: [false], byteOrder:[ModbusOrderType.BIG], security: [], @@ -126,14 +128,9 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat this.observeValueChanges(); this.observeTypeChange(); - this.observeFormEnable(); this.observeShowSecurity(); } - get isSlaveEnabled(): boolean { - return this.slaveConfigFormGroup.get('sendDataToThingsBoard').value; - } - get protocolType(): ModbusProtocolType { return this.slaveConfigFormGroup.get('type').value; } @@ -160,7 +157,11 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat writeValue(slaveConfig: ModbusSlave): void { this.showSecurityControl.patchValue(!!slaveConfig.security && !isEqual(slaveConfig.security, {})); this.updateSlaveConfig(slaveConfig); - this.updateFormEnableState(slaveConfig.sendDataToThingsBoard); + } + + setDisabledState(isDisabled: boolean): void { + this.isSlaveEnabled = !isDisabled; + this.updateFormEnableState(); } private observeValueChanges(): void { @@ -180,7 +181,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat this.slaveConfigFormGroup.get('type').valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(type => { - this.updateFormEnableState(this.isSlaveEnabled); + this.updateFormEnableState(); this.updateMethodType(type); }); } @@ -196,22 +197,15 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } } - private observeFormEnable(): void { - this.slaveConfigFormGroup.get('sendDataToThingsBoard').valueChanges - .pipe(startWith(this.isSlaveEnabled), takeUntil(this.destroy$)) - .subscribe(value => this.updateFormEnableState(value)); - } - - private updateFormEnableState(enabled: boolean): void { - if (enabled) { + private updateFormEnableState(): void { + if (this.isSlaveEnabled) { this.slaveConfigFormGroup.enable({emitEvent: false}); this.showSecurityControl.enable({emitEvent: false}); } else { this.slaveConfigFormGroup.disable({emitEvent: false}); this.showSecurityControl.disable({emitEvent: false}); - this.slaveConfigFormGroup.get('sendDataToThingsBoard').enable({emitEvent: false}); } - this.updateEnablingByProtocol(this.protocolType); + this.updateEnablingByProtocol(); this.updateSecurityEnable(this.showSecurityControl.value); } @@ -229,9 +223,10 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } } - private updateEnablingByProtocol(type: ModbusProtocolType): void { - const enableKeys = type === ModbusProtocolType.Serial ? this.serialSpecificControlKeys : this.tcpUdpSpecificControlKeys; - const disableKeys = type === ModbusProtocolType.Serial ? this.tcpUdpSpecificControlKeys : this.serialSpecificControlKeys; + private updateEnablingByProtocol(): void { + const isSerial = this.protocolType === ModbusProtocolType.Serial; + const enableKeys = isSerial ? this.serialSpecificControlKeys : this.tcpUdpSpecificControlKeys; + const disableKeys = isSerial ? this.tcpUdpSpecificControlKeys : this.serialSpecificControlKeys; if (this.isSlaveEnabled) { enableKeys.forEach(key => this.slaveConfigFormGroup.get(key)?.enable({ emitEvent: false })); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html index 1e47479f03..1cf95ad06e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html @@ -28,7 +28,7 @@
-
gateway.name
+
gateway.name
@@ -57,7 +57,7 @@ class="tb-form-row column-xs" fxLayoutAlign="space-between center" > -
gateway.host
+
gateway.host
@@ -77,7 +77,7 @@ class="tb-form-row column-xs" fxLayoutAlign="space-between center" > -
gateway.port
+
gateway.port
-
gateway.port
+
gateway.port
@@ -116,7 +116,7 @@
-
+
gateway.method
@@ -131,7 +131,7 @@
-
gateway.baudrate
+
gateway.baudrate
@@ -141,7 +141,7 @@
-
gateway.bytesize
+
gateway.bytesize
@@ -151,7 +151,7 @@
-
gateway.stopbits
+
gateway.stopbits
@@ -159,7 +159,7 @@
-
gateway.parity
+
gateway.parity
@@ -170,14 +170,14 @@
- + {{ 'gateway.strict' | translate }}
-
gateway.unit-id
+
gateway.unit-id
@@ -243,7 +243,7 @@
-
gateway.connection-timeout
+
gateway.connection-timeout
@@ -251,7 +251,7 @@
-
gateway.byte-order
+
gateway.byte-order
@@ -261,7 +261,7 @@
-
gateway.word-order
+
gateway.word-order
@@ -281,32 +281,36 @@ - +
- + {{ 'gateway.retries' | translate }}
- + {{ 'gateway.retries-on-empty' | translate }}
- + {{ 'gateway.retries-on-invalid' | translate }}
-
gateway.poll-period
+
+ + gateway.poll-period + +
@@ -314,7 +318,7 @@
-
gateway.connect-attempt-time
+
gateway.connect-attempt-time
@@ -322,7 +326,7 @@
-
gateway.connect-attempt-count
+
gateway.connect-attempt-count
@@ -330,7 +334,7 @@
-
gateway.wait-after-failed-attempts
+
gateway.wait-after-failed-attempts
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.scss index 8cea184957..0c68b6af9e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.scss @@ -18,4 +18,19 @@ width: 80vw; max-width: 900px; } + + .slave-name-label { + margin-right: 16px; + color: rgba(0, 0, 0, 0.87); + } + + .fixed-title-width-260 { + min-width: 260px; + } + + ::ng-deep.security-config { + .fixed-title-width { + min-width: 230px; + } + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts index a00a488aa0..3d2f5b6f5d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts @@ -52,6 +52,8 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { GatewayPortTooltipPipe } from '@home/components/widget/lib/gateway/pipes/gateway-port-tooltip.pipe'; import { takeUntil } from 'rxjs/operators'; import { isEqual } from '@core/utils'; +import { TruncateWithTooltipDirective } from '@shared/directives/truncate-with-tooltip.directive'; +import { helpBaseUrl } from '@shared/models/constants'; @Component({ selector: 'tb-modbus-slave-dialog', @@ -76,6 +78,7 @@ import { isEqual } from '@core/utils'; ModbusValuesComponent, ModbusSecurityConfigComponent, GatewayPortTooltipPipe, + TruncateWithTooltipDirective, ], styleUrls: ['./modbus-slave-dialog.component.scss'], }) @@ -97,7 +100,7 @@ export class ModbusSlaveDialogComponent extends DialogComponent void; + private onChange: (value: MQTTBasicConfig) => void; private onTouched: () => void; private destroy$ = new Subject(); @@ -100,7 +101,7 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(value => { - this.onChange(value); + this.onChange(this.getMappedMQTTConfig(value)); this.onTouched(); }); } @@ -110,7 +111,7 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator this.destroy$.complete(); } - registerOnChange(fn: (value: string) => void): void { + registerOnChange(fn: (value: MQTTBasicConfig) => void): void { this.onChange = fn; } @@ -135,13 +136,30 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator this.basicFormGroup.setValue(editedBase, {emitEvent: false}); } + private getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig { + let { broker, workers, dataMapping, requestsMapping } = basicConfig || {}; + + if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { + broker = { + ...broker, + ...workers, + }; + } + + if ((requestsMapping as RequestMappingData[])?.length) { + requestsMapping = this.getRequestDataObject(requestsMapping as RequestMappingData[]); + } + + return { broker, workers, dataMapping, requestsMapping }; + } + validate(): ValidationErrors | null { return this.basicFormGroup.valid ? null : { basicFormGroup: {valid: false} }; } - private getRequestDataArray(value: Record): RequestMappingData[] { + private getRequestDataArray(value: Record): RequestMappingData[] { const mappingConfigs = []; if (isObject(value)) { @@ -157,4 +175,17 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator return mappingConfigs; } + + private getRequestDataObject(array: RequestMappingData[]): Record { + return array.reduce((result, { requestType, requestValue }) => { + result[requestType].push(requestValue); + return result; + }, { + connectRequests: [], + disconnectRequests: [], + attributeRequests: [], + attributeUpdates: [], + serverSideRpc: [], + }); + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.html index 4c992c0e21..8c3f3aaf4b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.html @@ -34,12 +34,12 @@
-
+
{{ 'gateway.timeout' | translate }}
- +
-
- -
{{ valueTitle(keyControl.get('value').value) }}
+
{{ valueTitle(keyControl.get(keyControl.get('type').value).value) }}
@@ -54,13 +54,24 @@
gateway.value
- + + + + + + true + false + + warning diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component.scss index 687025e729..770f17cac6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component.scss @@ -18,9 +18,6 @@ .title-container { max-width: 11vw; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap } .key-panel { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component.ts index 32d0b2bddb..8e1c6fdb57 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component.ts @@ -18,6 +18,7 @@ import { Component, forwardRef, OnDestroy, OnInit } from '@angular/core'; import { AbstractControl, ControlValueAccessor, + FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, UntypedFormArray, @@ -28,6 +29,7 @@ import { } from '@angular/forms'; import { isDefinedAndNotNull } from '@core/utils'; import { + integerRegex, MappingDataKey, MappingValueType, mappingValueTypesMap, @@ -58,6 +60,7 @@ export class TypeValuePanelComponent implements ControlValueAccessor, Validator, valueTypeKeys: MappingValueType[] = Object.values(MappingValueType); valueTypes = mappingValueTypesMap; valueListFormArray: UntypedFormArray; + readonly MappingValueType = MappingValueType; private destroy$ = new Subject(); private propagateChange = (v: any) => {}; @@ -84,12 +87,26 @@ export class TypeValuePanelComponent implements ControlValueAccessor, Validator, addKey(): void { const dataKeyFormGroup = this.fb.group({ - type: [MappingValueType.STRING, []], - value: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]] + type: [MappingValueType.STRING], + string: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], + integer: [{value: 0, disabled: true}, [Validators.required, Validators.pattern(integerRegex)]], + double: [{value: 0, disabled: true}, [Validators.required]], + boolean: [{value: false, disabled: true}, [Validators.required]], }); + this.observeTypeChange(dataKeyFormGroup); this.valueListFormArray.push(dataKeyFormGroup); } + private observeTypeChange(dataKeyFormGroup: FormGroup): void { + dataKeyFormGroup.get('type').valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(type => { + dataKeyFormGroup.disable({emitEvent: false}); + dataKeyFormGroup.get('type').enable({emitEvent: false}); + dataKeyFormGroup.get(type).enable({emitEvent: false}); + }) + } + deleteKey($event: Event, index: number): void { if ($event) { $event.stopPropagation(); @@ -116,10 +133,17 @@ export class TypeValuePanelComponent implements ControlValueAccessor, Validator, writeValue(deviceInfoArray: Array): void { for (const deviceInfo of deviceInfoArray) { - const dataKeyFormGroup = this.fb.group({ - type: [deviceInfo.type, []], - value: [deviceInfo.value, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]] - }); + const config = { + type: [deviceInfo.type], + string: [{value: '', disabled: true}, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], + integer: [{value: 0, disabled: true}, [Validators.required, Validators.pattern(integerRegex)]], + double: [{value: 0, disabled: true}, [Validators.required]], + boolean: [{value: false, disabled: true}, [Validators.required]], + }; + config[deviceInfo.type][0] = {value: deviceInfo.value, disabled: false}; + + const dataKeyFormGroup = this.fb.group(config); + this.observeTypeChange(dataKeyFormGroup); this.valueListFormArray.push(dataKeyFormGroup); } } @@ -131,6 +155,6 @@ export class TypeValuePanelComponent implements ControlValueAccessor, Validator, } private updateView(value: any): void { - this.propagateChange(value); + this.propagateChange(value.map(({type, ...config}) => ({type, value: config[type]}))); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts index 5a1b5d2a1b..eca1497d22 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts @@ -34,6 +34,7 @@ import { import { Subject } from 'rxjs'; import { ResourcesService } from '@core/services/resources.service'; import { takeUntil, tap } from 'rxjs/operators'; +import { helpBaseUrl } from '@shared/models/constants'; @Component({ selector: 'tb-add-connector-dialog', @@ -83,7 +84,7 @@ export class AddConnectorDialogComponent extends DialogComponent { - const newName = c.value.trim().toLowerCase(); - const found = this.data.dataSourceData.find((connectorAttr) => { - const connectorData = connectorAttr.value; - return connectorData.name.toLowerCase() === newName; - }); - if (found) { - if (c.hasError('required')) { - return c.getError('required'); - } - return { - duplicateName: { - valid: false - } - }; - } - return null; + return (control: UntypedFormControl) => { + const newName = control.value.trim().toLowerCase(); + const isDuplicate = this.data.dataSourceData.some(({ value: { name } }) => + name.toLowerCase() === newName + ); + + return isDuplicate ? { duplicateName: { valid: false } } : null; }; } @@ -137,6 +128,6 @@ export class AddConnectorDialogComponent extends DialogComponent
- {{ initialConnector?.type ? gatewayConnectorDefaultTypes.get(initialConnector.type) : '' }} + {{ initialConnector?.type ? GatewayConnectorTypesTranslatesMap.get(initialConnector.type) : '' }} {{ 'gateway.configuration' | translate }}
- + {{ 'gateway.basic' | translate }} - + {{ 'gateway.advanced' | translate }} @@ -173,17 +173,17 @@ gateway.select-connector
- + - - - @@ -237,7 +237,7 @@
-
+
gateway.connectors-table-class
@@ -245,7 +245,7 @@
-
+
gateway.connectors-table-key
@@ -273,7 +273,7 @@
-
+
{{ 'gateway.send-change-data' | translate }} 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 e4c5360cdf..e7e4d05e45 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 @@ -31,7 +31,7 @@ import { EntityId } from '@shared/models/id/entity-id'; import { AttributeService } from '@core/http/attribute.service'; import { TranslateService } from '@ngx-translate/core'; import { forkJoin, Observable, of, Subject, Subscription } from 'rxjs'; -import { AttributeData, AttributeScope } from '@shared/models/telemetry/telemetry.models'; +import { AttributeScope } from '@shared/models/telemetry/telemetry.models'; import { PageComponent } from '@shared/components/page.component'; import { PageLink } from '@shared/models/page/page-link'; import { AttributeDatasource } from '@home/models/datasource/attribute-datasource'; @@ -51,8 +51,10 @@ import { EntityType } from '@shared/models/entity-type.models'; import { AddConnectorConfigData, ConnectorBaseConfig, + ConnectorBaseInfo, ConnectorConfigurationModes, ConnectorType, + GatewayAttributeData, GatewayConnector, GatewayConnectorDefaultTypesTranslatesMap, GatewayLogLevel, @@ -60,7 +62,7 @@ import { } from './gateway-widget.models'; import { MatDialog } from '@angular/material/dialog'; import { AddConnectorDialogComponent } from '@home/components/widget/lib/gateway/dialog/add-connector-dialog.component'; -import { debounceTime, take, takeUntil, tap } from 'rxjs/operators'; +import { debounceTime, filter, switchMap, take, takeUntil, tap } from 'rxjs/operators'; import { ErrorStateMatcher } from '@angular/material/core'; import { PageData } from '@shared/models/page/page-data'; @@ -80,59 +82,39 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie @Input() ctx: WidgetContext; - @Input() device: EntityId; @ViewChild('nameInput') nameInput: ElementRef; @ViewChild(MatSort, {static: false}) sort: MatSort; - pageLink: PageLink; - - connectorType = ConnectorType; - - allowBasicConfig = new Set([ + readonly ConnectorType = ConnectorType; + readonly allowBasicConfig = new Set([ ConnectorType.MQTT, ConnectorType.OPCUA, ConnectorType.MODBUS, ]); + readonly gatewayLogLevel = Object.values(GatewayLogLevel); + readonly displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions']; + readonly GatewayConnectorTypesTranslatesMap = GatewayConnectorDefaultTypesTranslatesMap; + readonly ConnectorConfigurationModes = ConnectorConfigurationModes; - gatewayLogLevel = Object.values(GatewayLogLevel); - - dataSource: MatTableDataSource; - - displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions']; - - gatewayConnectorDefaultTypes = GatewayConnectorDefaultTypesTranslatesMap; - - connectorConfigurationModes = ConnectorConfigurationModes; - + pageLink: PageLink; + dataSource: MatTableDataSource; connectorForm: FormGroup; - - textSearchMode: boolean; - activeConnectors: Array; - - mode: ConnectorConfigurationModes = this.connectorConfigurationModes.BASIC; - + mode: ConnectorConfigurationModes = this.ConnectorConfigurationModes.BASIC; initialConnector: GatewayConnector; private inactiveConnectors: Array; - private attributeDataSource: AttributeDatasource; - private inactiveConnectorsDataSource: AttributeDatasource; - private serverDataSource: AttributeDatasource; - private activeData: Array = []; - private inactiveData: Array = []; - - private sharedAttributeData: Array = []; - + private sharedAttributeData: Array = []; private basicConfigSub: Subscription; - + private jsonConfigSub: Subscription; private subscriptionOptions: WidgetSubscriptionOptions = { callbacks: { onDataUpdated: () => this.ctx.ngZone.run(() => { @@ -143,10 +125,9 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie }) } }; - private destroy$ = new Subject(); private subscription: IWidgetSubscription; - private attributeUpdateSubject = new Subject(); + private attributeUpdateSubject = new Subject(); constructor(protected store: Store, private fb: FormBuilder, @@ -159,112 +140,19 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie private utils: UtilsService, private cd: ChangeDetectorRef) { super(store); - const sortOrder: SortOrder = {property: 'key', direction: Direction.ASC}; - this.pageLink = new PageLink(1000, 0, null, sortOrder); - this.attributeDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); - this.inactiveConnectorsDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); - this.serverDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); - this.dataSource = new MatTableDataSource([]); - this.connectorForm = this.fb.group({ - mode: [ConnectorConfigurationModes.BASIC, []], - name: ['', [Validators.required, this.uniqNameRequired(), Validators.pattern(noLeadTrailSpacesRegex)]], - type: ['', [Validators.required]], - enableRemoteLogging: [false, []], - logLevel: ['', [Validators.required]], - sendDataOnlyOnChange: [false, []], - key: ['auto'], - class: [''], - configuration: [''], - configurationJson: [{}, [Validators.required]], - basicConfig: [{}] - }); - this.connectorForm.disable(); + this.initDataSources(); + this.initConnectorForm(); this.observeAttributeChange(); } ngAfterViewInit(): void { - this.connectorForm.get('type').valueChanges.pipe( - takeUntil(this.destroy$) - ).subscribe(type => { - if (type && !this.initialConnector) { - this.attributeService.getEntityAttributes(this.device, AttributeScope.CLIENT_SCOPE, - [`${type.toUpperCase()}_DEFAULT_CONFIG`], {ignoreErrors: true}).subscribe(defaultConfig=>{ - if (defaultConfig && defaultConfig.length) { - this.connectorForm.get('configurationJson').setValue( - isString(defaultConfig[0].value) ? - JSON.parse(defaultConfig[0].value) : - defaultConfig[0].value); - this.cd.detectChanges(); - } - }); - } - }); - - this.connectorForm.get('name').valueChanges.pipe( - takeUntil(this.destroy$) - ).subscribe((name) => { - if (this.connectorForm.get('type').value === ConnectorType.MQTT) { - this.connectorForm.get('basicConfig').get('broker.name')?.setValue(name); - } - }); - - this.connectorForm.get('configurationJson').valueChanges.pipe( - takeUntil(this.destroy$) - ).subscribe((config) => { - const basicConfig = this.connectorForm.get('basicConfig'); - const type = this.connectorForm.get('type').value; - const mode = this.connectorForm.get('mode').value; - if (!isEqual(config, basicConfig?.value) && this.allowBasicConfig.has(type) && mode === ConnectorConfigurationModes.ADVANCED) { - this.connectorForm.get('basicConfig').patchValue(config, {emitEvent: false}); - } - }); + this.observeName(); this.dataSource.sort = this.sort; - this.dataSource.sortingDataAccessor = (data: AttributeData, sortHeaderId: string) => { - switch (sortHeaderId) { - case 'syncStatus': - return this.isConnectorSynced(data) ? 1 : 0; - - case 'enabled': - return this.activeConnectors.includes(data.key) ? 1 : 0; - - case 'errors': - const errors = this.getErrorsCount(data); - if (typeof errors === 'string') { - return this.sort.direction.toUpperCase() === Direction.DESC ? -1 : Infinity; - } - return errors; - - default: - return data[sortHeaderId] || data.value[sortHeaderId]; - } - }; - - if (this.device) { - if (this.device.id === NULL_UUID) { - return; - } - forkJoin([ - this.attributeService.getEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, ['active_connectors']), - this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors']) - ]).subscribe(attributes => { - if (attributes.length) { - this.activeConnectors = attributes[0].length ? attributes[0][0].value : []; - this.activeConnectors = isString(this.activeConnectors) ? JSON.parse(this.activeConnectors as any) : this.activeConnectors; - this.inactiveConnectors = attributes[1].length ? attributes[1][0].value : []; - this.inactiveConnectors = isString(this.inactiveConnectors) - ? JSON.parse(this.inactiveConnectors as any) - : this.inactiveConnectors; - this.updateData(true); - } else { - this.activeConnectors = []; - this.inactiveConnectors = []; - this.updateData(true); - } - }); - } + this.dataSource.sortingDataAccessor = this.getSortingDataAccessor(); + this.loadConnectors(); this.observeModeChange(); } @@ -275,57 +163,12 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } saveConnector(): void { - const value = this.connectorForm.get('type').value === ConnectorType.MQTT ? this.getMappedMQTTValue() : this.connectorForm.value; - value.configuration = camelCase(value.name) + '.json'; - delete value.basicConfig; - if (value.type !== ConnectorType.GRPC) { - delete value.key; - } - if (value.type !== ConnectorType.CUSTOM) { - delete value.class; - } - value.ts = new Date().getTime(); - const attributesToSave = [{ - key: value.name, - value - }]; - const attributesToDelete = []; + const value = this.getConnectorData(); const scope = (!this.initialConnector || this.activeConnectors.includes(this.initialConnector.name)) - ? AttributeScope.SHARED_SCOPE - : AttributeScope.SERVER_SCOPE; - let updateActiveConnectors = false; - if (this.initialConnector && this.initialConnector.name !== value.name) { - attributesToDelete.push({key: this.initialConnector.name}); - updateActiveConnectors = true; - const activeIndex = this.activeConnectors.indexOf(this.initialConnector.name); - const inactiveIndex = this.inactiveConnectors.indexOf(this.initialConnector.name); - if (activeIndex !== -1) { - this.activeConnectors.splice(activeIndex, 1); - } - if (inactiveIndex !== -1) { - this.inactiveConnectors.splice(inactiveIndex, 1); - } - } - if (!this.activeConnectors.includes(value.name) && scope === AttributeScope.SHARED_SCOPE) { - this.activeConnectors.push(value.name); - updateActiveConnectors = true; - } - if (!this.inactiveConnectors.includes(value.name) && scope === AttributeScope.SERVER_SCOPE) { - this.inactiveConnectors.push(value.name); - updateActiveConnectors = true; - } - const tasks = [this.attributeService.saveEntityAttributes(this.device, scope, attributesToSave)]; - if (updateActiveConnectors) { - tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, [{ - key: scope === AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors', - value: scope === AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors - }])); - } + ? AttributeScope.SHARED_SCOPE + : AttributeScope.SERVER_SCOPE; - if (attributesToDelete.length) { - tasks.push(this.attributeService.deleteEntityAttributes(this.device, scope, attributesToDelete)); - } - forkJoin(tasks).subscribe(_ => { + forkJoin(this.getEntityAttributeTasks(value, scope)).pipe(take(1)).subscribe(_ => { this.showToast(!this.initialConnector ? this.translate.instant('gateway.connector-created') : this.translate.instant('gateway.connector-updated') @@ -336,18 +179,71 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie }); } - private getMappedMQTTValue(): GatewayConnector { - const value = this.connectorForm.value; - return { - ...value, - configurationJson: { - ...value.configurationJson, - broker: { - ...value.configurationJson.broker, - ...value.configurationJson.workers, - } + private getEntityAttributeTasks(value: GatewayConnector, scope: AttributeScope): Observable[] { + const tasks = []; + const attributesToSave = [{ key: value.name, value }]; + const attributesToDelete = []; + const shouldAddToConnectorsList = !this.activeConnectors.includes(value.name) && scope === AttributeScope.SHARED_SCOPE + || !this.inactiveConnectors.includes(value.name) && scope === AttributeScope.SERVER_SCOPE; + const isNewConnector = this.initialConnector && this.initialConnector.name !== value.name; + + if (isNewConnector) { + attributesToDelete.push({ key: this.initialConnector.name }); + this.removeConnectorFromList(this.initialConnector.name, true); + this.removeConnectorFromList(this.initialConnector.name, false); + } + + if (shouldAddToConnectorsList) { + if (scope === AttributeScope.SHARED_SCOPE) { + this.activeConnectors.push(value.name); + } else { + this.inactiveConnectors.push(value.name); } - }; + } + + if (isNewConnector || shouldAddToConnectorsList) { + tasks.push(this.getSaveEntityAttributesTask(scope)); + } + + tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, attributesToSave)); + + if (attributesToDelete.length) { + tasks.push(this.attributeService.deleteEntityAttributes(this.device, scope, attributesToDelete)); + } + + return tasks; + } + + private getSaveEntityAttributesTask(scope: AttributeScope): Observable { + const key = scope === AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors'; + const value = scope === AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors; + + return this.attributeService.saveEntityAttributes(this.device, scope, [{ key, value }]); + } + + private removeConnectorFromList(connectorName: string, isActive: boolean): void { + const list = isActive? this.activeConnectors : this.inactiveConnectors; + const index = list.indexOf(connectorName); + if (index !== -1) { + list.splice(index, 1); + } + } + + private getConnectorData(): GatewayConnector { + const value = { ...this.connectorForm.value }; + value.configuration = `${camelCase(value.name)}.json`; + delete value.basicConfig; + + if (value.type !== ConnectorType.GRPC) { + delete value.key; + } + if (value.type !== ConnectorType.CUSTOM) { + delete value.class; + } + + value.ts = Date.now(); + + return value; } private updateData(reload: boolean = false): void { @@ -369,13 +265,13 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie }); } - isConnectorSynced(attribute: AttributeData) { + isConnectorSynced(attribute: GatewayAttributeData) { const connectorData = attribute.value; - if (!connectorData.ts) { + if (!connectorData.ts || attribute.skipSync) { return false; } const clientIndex = this.activeData.findIndex(data => { - const sharedData = data.value; + const sharedData = typeof data.value === 'string' ? JSON.parse(data.value) : data.value; return sharedData.name === connectorData.name; }); if (clientIndex === -1) { @@ -383,18 +279,54 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } const sharedIndex = this.sharedAttributeData.findIndex(data => { const sharedData = data.value; - return sharedData.name === connectorData.name && sharedData.ts && sharedData.ts <= connectorData.ts; + const hasSameName = sharedData.name === connectorData.name; + const hasEmptyConfig = isEqual(sharedData.configurationJson, {}) && hasSameName; + const hasSameConfig = this.hasSameConfig(sharedData.configurationJson, connectorData.configurationJson); + const isRecentlyCreated = sharedData.ts && sharedData.ts <= connectorData.ts; + return hasSameName && isRecentlyCreated && (hasSameConfig || hasEmptyConfig); }); return sharedIndex !== -1; } + private hasSameConfig(sharedDataConfigJson: ConnectorBaseInfo, connectorDataConfigJson: ConnectorBaseInfo): boolean { + const { name, id, enableRemoteLogging, logLevel, ...sharedDataConfig } = sharedDataConfigJson; + const { + name: connectorName, + id: connectorId, + enableRemoteLogging: connectorEnableRemoteLogging, + logLevel: connectorLogLevel, + ...connectorConfig + } = connectorDataConfigJson; + + return isEqual(sharedDataConfig, connectorConfig); + } + private combineData(): void { - this.dataSource.data = [...this.activeData, ...this.inactiveData, ...this.sharedAttributeData].filter((item, index, self) => - index === self.findIndex((t) => t.key === item.key) - ).map(attribute => { - attribute.value = typeof attribute.value === 'string' ? JSON.parse(attribute.value) : attribute.value; - return attribute; - }); + const combinedData = [ + ...this.activeData, + ...this.inactiveData, + ...this.sharedAttributeData + ]; + + const latestData = combinedData.reduce((acc, attribute) => { + const existingItemIndex = acc.findIndex(item => item.key === attribute.key); + + if (existingItemIndex === -1) { + acc.push(attribute); + } else if ( + attribute.lastUpdateTs > acc[existingItemIndex].lastUpdateTs && + !this.isConnectorSynced(acc[existingItemIndex]) + ) { + acc[existingItemIndex] = { ...attribute, skipSync: true }; + } + + return acc; + }, []); + + this.dataSource.data = latestData.map(attribute => ({ + ...attribute, + value: typeof attribute.value === 'string' ? JSON.parse(attribute.value) : attribute.value + })); } private clearOutConnectorForm(): void { @@ -415,7 +347,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie this.connectorForm.markAsPristine(); } - selectConnector($event: Event, attribute: AttributeData): void { + selectConnector($event: Event, attribute: GatewayAttributeData): void { if ($event) { $event.stopPropagation(); } @@ -429,7 +361,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } } - isSameConnector(attribute: AttributeData): boolean { + isSameConnector(attribute: GatewayAttributeData): boolean { if (!this.initialConnector) { return false; } @@ -450,49 +382,45 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie })); } - returnType(attribute: AttributeData): string { + returnType(attribute: GatewayAttributeData): string { const value = attribute.value; - return this.gatewayConnectorDefaultTypes.get(value.type); + return this.GatewayConnectorTypesTranslatesMap.get(value.type); } - deleteConnector(attribute: AttributeData, $event: Event): void { - if ($event) { - $event.stopPropagation(); - } + deleteConnector(attribute: GatewayAttributeData, $event: Event): void { + $event?.stopPropagation(); + const title = `Delete connector \"${attribute.key}\"?`; const content = `All connector data will be deleted.`; - this.dialogService.confirm(title, content, 'Cancel', 'Delete').subscribe(result => { - if (result) { + + this.dialogService.confirm(title, content, 'Cancel', 'Delete').pipe( + take(1), + switchMap((result) => { + if (!result) { + return; + } const tasks: Array> = []; const scope = this.activeConnectors.includes(attribute.value?.name) ? - AttributeScope.SHARED_SCOPE : - AttributeScope.SERVER_SCOPE; + AttributeScope.SHARED_SCOPE : + AttributeScope.SERVER_SCOPE; tasks.push(this.attributeService.deleteEntityAttributes(this.device, scope, [attribute])); - const activeIndex = this.activeConnectors.indexOf(attribute.key); - const inactiveIndex = this.inactiveConnectors.indexOf(attribute.key); - if (activeIndex !== -1) { - this.activeConnectors.splice(activeIndex, 1); - } - if (inactiveIndex !== -1) { - this.inactiveConnectors.splice(inactiveIndex, 1); - } - tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, [{ - key: scope === AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors', - value: scope === AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors - }])); - forkJoin(tasks).subscribe(() => { - if (this.initialConnector ? this.initialConnector.name === attribute.key : true) { - this.clearOutConnectorForm(); - this.cd.detectChanges(); - this.connectorForm.disable(); - } - this.updateData(true); - }); + this.removeConnectorFromList(attribute.key, true); + this.removeConnectorFromList(attribute.key, false); + tasks.push(this.getSaveEntityAttributesTask(scope)); + + return forkJoin(tasks); + }) + ).subscribe(() => { + if (this.initialConnector ? this.initialConnector.name === attribute.key : true) { + this.clearOutConnectorForm(); + this.cd.detectChanges(); + this.connectorForm.disable(); } + this.updateData(true); }); } - connectorLogs(attribute: AttributeData, $event: Event): void { + connectorLogs(attribute: GatewayAttributeData, $event: Event): void { if ($event) { $event.stopPropagation(); } @@ -502,7 +430,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie this.ctx.stateController.openState('connector_logs', params); } - connectorRpc(attribute: AttributeData, $event: Event): void { + connectorRpc(attribute: GatewayAttributeData, $event: Event): void { if ($event) { $event.stopPropagation(); } @@ -513,7 +441,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } - onEnableConnector(attribute: AttributeData): void { + onEnableConnector(attribute: GatewayAttributeData): void { attribute.value.ts = new Date().getTime(); this.updateActiveConnectorKeys(attribute.key); @@ -521,70 +449,142 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie this.attributeUpdateSubject.next(attribute); } - getErrorsCount(attribute: AttributeData): string { + getErrorsCount(attribute: GatewayAttributeData): string { const connectorName = attribute.key; const connector = this.subscription && this.subscription.data .find(data => data && data.dataKey.name === `${connectorName}_ERRORS_COUNT`); return (connector && this.activeConnectors.includes(connectorName)) ? (connector.data[0][1] || 0) : 'Inactive'; } - addConnector($event: Event) { - if ($event) { - $event.stopPropagation(); - } - this.confirmConnectorChange().subscribe((changeConfirmed) => { - if (changeConfirmed) { - return this.dialog.open(AddConnectorDialogComponent, { - disableClose: true, - panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], - data: { - dataSourceData: this.dataSource.data - } - }).afterClosed().subscribe((value) => { - if (value && changeConfirmed) { - this.initialConnector = null; - if (this.connectorForm.disabled) { - this.connectorForm.enable(); - } - if (!value.configurationJson) { - value.configurationJson = {}; - } - value.basicConfig = value.configurationJson; - this.updateConnector(value); - this.generate('basicConfig.broker.clientId'); - setTimeout(() => this.saveConnector()); - } - }); - } + addConnector(event?: Event): void { + event?.stopPropagation(); + + this.confirmConnectorChange() + .pipe( + take(1), + filter(Boolean), + switchMap(() => this.openAddConnectorDialog()), + filter(Boolean), + ) + .subscribe(value => { + this.initialConnector = null; + if (this.connectorForm.disabled) { + this.connectorForm.enable(); + } + if (!value.configurationJson) { + value.configurationJson = {} as ConnectorBaseConfig; + } + value.basicConfig = value.configurationJson; + this.updateConnector(value); + this.generate('basicConfig.broker.clientId'); + setTimeout(() => this.saveConnector()); }); } + private openAddConnectorDialog(): Observable { + return this.dialog.open(AddConnectorDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { dataSourceData: this.dataSource.data } + }).afterClosed(); + } + generate(formControlName: string): void { this.connectorForm.get(formControlName)?.patchValue('tb_gw_' + generateSecret(5)); } uniqNameRequired(): ValidatorFn { - return (c: UntypedFormControl) => { - const newName = c.value.trim().toLowerCase(); - const found = this.dataSource.data.find((connectorAttr) => { - const connectorData = connectorAttr.value; - return connectorData.name.toLowerCase() === newName; - }); - if (found) { - if (this.initialConnector && this.initialConnector.name.toLowerCase() === newName) { - return null; - } - return { - duplicateName: { - valid: false - } - }; + return (control: UntypedFormControl) => { + const newName = control.value?.trim().toLowerCase(); + const isDuplicate = this.dataSource.data.some(connectorAttr => connectorAttr.value.name.toLowerCase() === newName); + const isSameAsInitial = this.initialConnector?.name.toLowerCase() === newName; + + if (isDuplicate && !isSameAsInitial) { + return { duplicateName: { valid: false } }; } + return null; }; } + private initDataSources(): void { + const sortOrder: SortOrder = {property: 'key', direction: Direction.ASC}; + this.pageLink = new PageLink(1000, 0, null, sortOrder); + this.attributeDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); + this.inactiveConnectorsDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); + this.serverDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); + this.dataSource = new MatTableDataSource([]); + } + + private initConnectorForm(): void { + this.connectorForm = this.fb.group({ + mode: [ConnectorConfigurationModes.BASIC], + name: ['', [Validators.required, this.uniqNameRequired(), Validators.pattern(noLeadTrailSpacesRegex)]], + type: ['', [Validators.required]], + enableRemoteLogging: [false], + logLevel: ['', [Validators.required]], + sendDataOnlyOnChange: [false], + key: ['auto'], + class: [''], + configuration: [''], + configurationJson: [{}, [Validators.required]], + basicConfig: [{}] + }); + this.connectorForm.disable(); + } + + private observeName(): void { + this.connectorForm.get('name').valueChanges + .pipe( + filter(() => this.connectorForm.get('type').value === ConnectorType.MQTT), + takeUntil(this.destroy$) + ) + .subscribe(name => this.connectorForm.get('basicConfig').get('broker.name')?.setValue(name)); + } + + private getSortingDataAccessor(): (data: GatewayAttributeData, sortHeaderId: string) => string | number { + return (data: GatewayAttributeData, sortHeaderId: string) => { + switch (sortHeaderId) { + case 'syncStatus': + return this.isConnectorSynced(data) ? 1 : 0; + + case 'enabled': + return this.activeConnectors.includes(data.key) ? 1 : 0; + + case 'errors': + const errors = this.getErrorsCount(data); + if (typeof errors === 'string') { + return this.sort.direction.toUpperCase() === Direction.DESC ? -1 : Infinity; + } + return errors; + + default: + return data[sortHeaderId] || data.value[sortHeaderId]; + } + }; + } + + private loadConnectors(): void { + if (!this.device || this.device.id === NULL_UUID) { + return; + } + + forkJoin([ + this.attributeService.getEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, ['active_connectors']), + this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors']) + ]).pipe(takeUntil(this.destroy$)).subscribe(attributes => { + this.activeConnectors = this.parseConnectors(attributes[0]); + this.inactiveConnectors = this.parseConnectors(attributes[1]); + + this.updateData(true); + }); + } + + private parseConnectors(attribute: GatewayAttributeData[]): string[] { + const connectors = attribute?.[0]?.value || []; + return isString(connectors) ? JSON.parse(connectors) : connectors; + } + private observeModeChange(): void { this.connectorForm.get('mode').valueChanges .pipe(takeUntil(this.destroy$)) @@ -594,7 +594,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie private observeAttributeChange(): void { this.attributeUpdateSubject.pipe( debounceTime(300), - tap((attribute: AttributeData) => this.executeAttributeUpdates(attribute)), + tap((attribute: GatewayAttributeData) => this.executeAttributeUpdates(attribute)), takeUntil(this.destroy$), ).subscribe(); } @@ -616,7 +616,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } } - private executeAttributeUpdates(attribute: AttributeData): void { + private executeAttributeUpdates(attribute: GatewayAttributeData): void { forkJoin(this.getAttributeExecutionTasks(attribute)) .pipe( take(1), @@ -626,7 +626,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie .subscribe(); } - private getAttributeExecutionTasks(attribute: AttributeData): Observable[] { + private getAttributeExecutionTasks(attribute: GatewayAttributeData): Observable[] { const isActive = this.activeConnectors.includes(attribute.key); const scopeOld = isActive ? AttributeScope.SERVER_SCOPE : AttributeScope.SHARED_SCOPE; const scopeNew = isActive ? AttributeScope.SHARED_SCOPE : AttributeScope.SERVER_SCOPE; @@ -641,7 +641,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie value: this.inactiveConnectors }]), this.attributeService.deleteEntityAttributes(this.device, scopeOld, [attribute]), - this.attributeService.saveEntityAttributes(this.device, scopeNew, [attribute])]; + this.attributeService.saveEntityAttributes(this.device, scopeNew, [attribute]) + ]; } private onDataUpdateError(e: any): void { @@ -684,6 +685,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie this.basicConfigSub.unsubscribe(); } this.basicConfigSub = this.connectorForm.get('basicConfig').valueChanges.pipe( + filter(() => !!this.initialConnector), takeUntil(this.destroy$) ).subscribe((config) => { const configJson = this.connectorForm.get('configurationJson'); @@ -696,6 +698,22 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie }); } + private createJsonConfigWatcher(): void { + if (this.jsonConfigSub) { + this.jsonConfigSub.unsubscribe(); + } + this.jsonConfigSub = this.connectorForm.get('configurationJson').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((config) => { + const basicConfig = this.connectorForm.get('basicConfig'); + const type = this.connectorForm.get('type').value; + const mode = this.connectorForm.get('mode').value; + if (!isEqual(config, basicConfig?.value) && this.allowBasicConfig.has(type) && mode === ConnectorConfigurationModes.ADVANCED) { + this.connectorForm.get('basicConfig').patchValue(config, {emitEvent: false}); + } + }); + } + private confirmConnectorChange(): Observable { if (this.initialConnector && this.connectorForm.dirty) { return this.dialogService.confirm( @@ -713,20 +731,17 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie if (this.connectorForm.disabled) { this.connectorForm.enable(); } - if (!connector.configuration) { - connector.configuration = ''; - } - if (!connector.key) { - connector.key = 'auto'; - } - if (!connector.configurationJson) { - connector.configurationJson = {} as ConnectorBaseConfig; - } - connector.basicConfig = connector.configurationJson; - this.initialConnector = connector; + const connectorState = { + configuration: '', + key: 'auto', + configurationJson: {} as ConnectorBaseConfig, + ...connector, + }; - this.updateConnector(connector); + connectorState.basicConfig = connectorState.configurationJson; + this.initialConnector = connectorState; + this.updateConnector(connectorState); } private updateConnector(connector: GatewayConnector): void { @@ -734,22 +749,21 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie case ConnectorType.MQTT: case ConnectorType.OPCUA: case ConnectorType.MODBUS: - this.connectorForm.get('type').patchValue(connector.type, {emitValue: false, onlySelf: true}); - this.connectorForm.get('basicConfig').setValue({}, {emitEvent: false}); - + this.connectorForm.get('mode').setValue(connector.mode || ConnectorConfigurationModes.BASIC, {emitEvent: false}); setTimeout(() => { - this.connectorForm.patchValue({...connector, mode: connector.mode || ConnectorConfigurationModes.BASIC}); - this.createBasicConfigWatcher(); + this.connectorForm.patchValue(connector, {emitEvent: false}); this.connectorForm.markAsPristine(); + this.createBasicConfigWatcher(); }); break; default: this.connectorForm.patchValue({...connector, mode: null}); this.connectorForm.markAsPristine(); } + this.createJsonConfigWatcher(); } - private setClientData(data: PageData): void { + private setClientData(data: PageData): void { if (this.initialConnector) { const clientConnectorData = data.data.find(attr => attr.key === this.initialConnector.name); if (clientConnectorData) { 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 eb428bebdc..3e94ae96d7 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 @@ -50,46 +50,6 @@ placeholder="${params}"/> - - - {{ 'gateway.rpc.tag' | translate }} - - -
- - {{ 'gateway.rpc.type' | translate }} - - - {{ type }} - - - - - {{ 'gateway.rpc.functionCode' | translate }} - - - {{ modbusCodesTranslate.get(code) | translate}} - - - -
- - {{ 'gateway.rpc.value' | translate }} - - -
- - {{ 'gateway.rpc.address' | translate }} - - - - {{ 'gateway.rpc.objectsCount' | translate }} - - -
-
{{ 'gateway.rpc.methodRPC' | translate }} 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 3027cafa8d..989f9daeed 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 @@ -35,8 +35,6 @@ import { ConnectorType, GatewayConnectorDefaultTypesTranslatesMap, HTTPMethods, - ModbusCodesTranslate, - ModbusCommandTypes, noLeadTrailSpacesRegex, RPCCommand, RPCTemplateConfig, @@ -53,7 +51,7 @@ import { } from '@shared/components/dialog/json-object-edit-dialog.component'; import { jsonRequired } from '@shared/components/json-object-edit.component'; import { deepClone } from '@core/utils'; -import { filter, takeUntil, tap } from "rxjs/operators"; +import { takeUntil, tap } from "rxjs/operators"; import { Subject } from "rxjs"; @Component({ @@ -80,9 +78,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, OnDestroy, C saveTemplate: EventEmitter = new EventEmitter(); commandForm: FormGroup; - codesArray: Array = [1, 2, 3, 4, 5, 6, 15, 16]; ConnectorType = ConnectorType; - modbusCommandTypes = Object.values(ModbusCommandTypes) as ModbusCommandTypes[]; bACnetRequestTypes = Object.values(BACnetRequestTypes) as BACnetRequestTypes[]; bACnetObjectTypes = Object.values(BACnetObjectTypes) as BACnetObjectTypes[]; bLEMethods = Object.values(BLEMethods) as BLEMethods[]; @@ -98,7 +94,6 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, OnDestroy, C SocketMethodProcessingsTranslates = SocketMethodProcessingsTranslates; SNMPMethodsTranslations = SNMPMethodsTranslations; gatewayConnectorDefaultTypesTranslates = GatewayConnectorDefaultTypesTranslatesMap; - modbusCodesTranslate = ModbusCodesTranslate; urlPattern = /^[-a-zA-Zd_$:{}?~+=\/.0-9-]*$/; numbersOnlyPattern = /^[0-9]*$/; @@ -156,26 +151,6 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, OnDestroy, C withResponse: [false, []], }); break; - case ConnectorType.MODBUS: - formGroup = this.fb.group({ - tag: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], - type: [null, [Validators.required]], - functionCode: [null, [Validators.required]], - value: [null, []], - address: [null, [Validators.required, Validators.min(0), Validators.pattern(this.numbersOnlyPattern)]], - objectsCount: [null, [Validators.required, Validators.min(0), Validators.pattern(this.numbersOnlyPattern)]] - }) - const valueForm = formGroup.get('value'); - formGroup.get('functionCode').valueChanges.subscribe(value => { - if (value > 4) { - valueForm.addValidators([Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]); - } else { - valueForm.clearValidators(); - valueForm.setValue(null); - } - valueForm.updateValueAndValidity(); - }) - break; case ConnectorType.BACNET: formGroup = this.fb.group({ method: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html index 8368698087..41dea0b656 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html @@ -41,8 +41,32 @@ - + + +
+
{{ 'gateway.rpc.title' | translate: {type: gatewayConnectorDefaultTypesTranslates.get(connectorType)} }}
+ +
+ + +
+
+
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 f74097bbba..b8424dc068 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 @@ -40,6 +40,10 @@ } } + .rpc-parameters { + width: 100%; + } + .result-block { padding: 0 5px; display: flex; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts index 1f3327ec06..d6b20d0137 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts @@ -22,6 +22,7 @@ import { ContentType } from '@shared/models/constants'; import { jsonRequired } from '@shared/components/json-object-edit.component'; import { ConnectorType, + GatewayConnectorDefaultTypesTranslatesMap, RPCCommand, RPCTemplate, RPCTemplateConfig, @@ -71,6 +72,9 @@ export class GatewayServiceRPCComponent implements OnInit { public connectorType: ConnectorType; public templates: Array = []; + readonly ConnectorType = ConnectorType; + readonly gatewayConnectorDefaultTypesTranslates = GatewayConnectorDefaultTypesTranslatesMap; + private subscription: IWidgetSubscription; private subscriptionOptions: WidgetSubscriptionOptions = { callbacks: { 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 8df3994ea2..8ee57e068f 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 @@ -16,9 +16,11 @@ import { ResourcesService } from '@core/services/resources.service'; import { Observable } from 'rxjs'; -import { ValueTypeData } from '@shared/models/constants'; +import { helpBaseUrl, ValueTypeData } from '@shared/models/constants'; +import { AttributeData } from '@shared/models/telemetry/telemetry.models'; -export const noLeadTrailSpacesRegex = /^(?! )[\S\s]*(?( ] ); +export interface GatewayAttributeData extends AttributeData { + skipSync?: boolean; +} + export interface GatewayConnector { name: string; type: ConnectorType; @@ -170,19 +176,27 @@ export interface ConnectorSecurity { pathToCACert?: string; pathToPrivateKey?: string; pathToClientCert?: string; + mode?: ModeType; } export type ConnectorMapping = DeviceConnectorMapping | RequestMappingData | ConverterConnectorMapping; export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingFormValue | ConverterMappingFormValue; -export type ConnectorBaseConfig = MQTTBasicConfig | OPCBasicConfig | ModbusBasicConfig; +export type ConnectorBaseConfig = ConnectorBaseInfo | MQTTBasicConfig | OPCBasicConfig | ModbusBasicConfig; + +export interface ConnectorBaseInfo { + name: string; + id: string; + enableRemoteLogging: boolean; + logLevel: GatewayLogLevel; +} export interface MQTTBasicConfig { dataMapping: ConverterConnectorMapping[]; - requestsMapping: Record | RequestMappingData[]; + requestsMapping: Record | RequestMappingData[]; broker: BrokerConfig; - workers: WorkersConfig; + workers?: WorkersConfig; } export interface OPCBasicConfig { @@ -311,35 +325,15 @@ export interface RPCCommand { time: number; } - -export enum ModbusCommandTypes { - Bits = 'bits', - Bit = 'bit', - // eslint-disable-next-line id-blacklist - String = 'string', - Bytes = 'bytes', - Int8 = '8int', - Uint8 = '8uint', - Int16 = '16int', - Uint16 = '16uint', - Float16 = '16float', - Int32 = '32int', - Uint32 = '32uint', - Float32 = '32float', - Int64 = '64int', - Uint64 = '64uint', - Float64 = '64float' -} - -export const ModbusCodesTranslate = new Map([ - [1, 'gateway.rpc.read-coils'], - [2, 'gateway.rpc.read-discrete-inputs'], - [3, 'gateway.rpc.read-multiple-holding-registers'], - [4, 'gateway.rpc.read-input-registers'], - [5, 'gateway.rpc.write-single-coil'], - [6, 'gateway.rpc.write-single-holding-register'], - [15, 'gateway.rpc.write-multiple-coils'], - [16, 'gateway.rpc.write-multiple-holding-registers'] +export const ModbusFunctionCodeTranslationsMap = new Map([ + [1, 'gateway.function-codes.read-coils'], + [2, 'gateway.function-codes.read-discrete-inputs'], + [3, 'gateway.function-codes.read-multiple-holding-registers'], + [4, 'gateway.function-codes.read-input-registers'], + [5, 'gateway.function-codes.write-single-coil'], + [6, 'gateway.function-codes.write-single-holding-register'], + [15, 'gateway.function-codes.write-multiple-coils'], + [16, 'gateway.function-codes.write-multiple-holding-registers'] ]); export enum BACnetRequestTypes { @@ -565,9 +559,9 @@ export const MappingHintTranslationsMap = new Map( export const HelpLinkByMappingTypeMap = new Map( [ - [MappingType.DATA, 'https://thingsboard.io/docs/iot-gateway/config/mqtt/#section-mapping'], - [MappingType.OPCUA, 'https://thingsboard.io/docs/iot-gateway/config/opc-ua/#section-mapping'], - [MappingType.REQUESTS, 'https://thingsboard.io/docs/iot-gateway/config/mqtt/#section-mapping'] + [MappingType.DATA, helpBaseUrl + '/docs/iot-gateway/config/mqtt/#section-mapping'], + [MappingType.OPCUA, helpBaseUrl + '/docs/iot-gateway/config/opc-ua/#section-mapping'], + [MappingType.REQUESTS, helpBaseUrl + '/docs/iot-gateway/config/mqtt/#section-mapping'] ] ); @@ -862,6 +856,8 @@ export enum ModbusDataType { FLOAT64 = '64float' } +export const ModbusEditableDataTypes = [ModbusDataType.BYTES, ModbusDataType.BITS, ModbusDataType.STRING]; + export enum ModbusObjectCountByDataType { '8int' = 1, '8uint' = 1, @@ -920,19 +916,6 @@ export const ModbusKeysNoKeysTextTranslationsMap = new Map( - [ - [1, 'gateway.read-coils'], - [2, 'gateway.read-discrete-inputs'], - [3, 'gateway.read-multiple-holding-registers'], - [4, 'gateway.read-input-registers'], - [5, 'gateway.write-coil'], - [6, 'gateway.write-register'], - [15, 'gateway.write-coils'], - [16, 'gateway.write-registers'], - ] -); - export interface ModbusMasterConfig { slaves: SlaveConfig[]; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts index 38bd5993ff..8beac3fb32 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts @@ -112,7 +112,7 @@ export interface ScadaSymbolBehaviorBase { export interface ScadaSymbolBehaviorValue extends ScadaSymbolBehaviorBase { valueType: ValueType; - defaultValue: any; + defaultGetValueSettings?: GetValueSettings; trueLabel?: string; falseLabel?: string; stateLabel?: string; @@ -120,9 +120,8 @@ export interface ScadaSymbolBehaviorValue extends ScadaSymbolBehaviorBase { export interface ScadaSymbolBehaviorAction extends ScadaSymbolBehaviorBase { valueType: ValueType; - valueToDataType: ValueToDataType; - constantValue: any; - valueToDataFunction: string; + defaultSetValueSettings?: SetValueSettings; + defaultWidgetActionSettings?: WidgetAction; } export type ScadaSymbolBehavior = ScadaSymbolBehaviorValue & ScadaSymbolBehaviorAction; @@ -312,30 +311,47 @@ export const scadaSymbolContentData = (svgContent: string): ScadaSymbolContentDa return result; }; -const defaultGetValueSettings = (get: ScadaSymbolBehaviorValue): GetValueSettings => ({ - action: GetValueAction.DO_NOTHING, - defaultValue: get.defaultValue, - executeRpc: { +const defaultValueForValueType = (valueType: ValueType): any => { + if (!valueType) { + return null; + } + switch (valueType) { + case ValueType.STRING: + return ''; + case ValueType.INTEGER: + case ValueType.DOUBLE: + return 0; + case ValueType.BOOLEAN: + return false; + case ValueType.JSON: + return {}; + } +}; + +export const defaultGetValueSettings = (valueType: ValueType): GetValueSettings => ({ + action: GetValueAction.DO_NOTHING, + defaultValue: defaultValueForValueType(valueType), + 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;' - } - }); + 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;' + } +}); -const defaultSetValueSettings = (set: ScadaSymbolBehaviorAction): SetValueSettings => ({ +export const defaultSetValueSettings = (valueType: ValueType): SetValueSettings => ({ action: SetValueAction.EXECUTE_RPC, executeRpc: { method: 'setState', @@ -351,20 +367,49 @@ const defaultSetValueSettings = (set: ScadaSymbolBehaviorAction): SetValueSettin key: 'state' }, valueToData: { - type: set.valueToDataType, - constantValue: set.constantValue, - valueToDataFunction: set.valueToDataFunction ? set.valueToDataFunction : + type: valueType !== ValueType.BOOLEAN ? ValueToDataType.VALUE : ValueToDataType.CONSTANT, + constantValue: false, + valueToDataFunction: '/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;' } }); -const defaultWidgetActionSettings = (widgetAction: ScadaSymbolBehavior): WidgetAction => ({ +export const defaultWidgetActionSettings: WidgetAction = { type: WidgetActionType.doNothing, targetDashboardStateId: null, openRightLayout: false, setEntityId: false, stateEntityParamName: null -}); +}; + +export const updateBehaviorDefaultSettings = (behavior: ScadaSymbolBehavior): ScadaSymbolBehavior => { + if (behavior.type) { + switch (behavior.type) { + case ScadaSymbolBehaviorType.value: + delete behavior.defaultSetValueSettings; + delete behavior.defaultWidgetActionSettings; + if (!behavior.defaultGetValueSettings) { + behavior.defaultGetValueSettings = mergeDeep({} as GetValueSettings, defaultGetValueSettings(behavior.valueType)); + } + break; + case ScadaSymbolBehaviorType.action: + delete behavior.defaultGetValueSettings; + delete behavior.defaultWidgetActionSettings; + if (!behavior.defaultSetValueSettings) { + behavior.defaultSetValueSettings = mergeDeep({} as SetValueSettings, defaultSetValueSettings(behavior.valueType)); + } + break; + case ScadaSymbolBehaviorType.widgetAction: + delete behavior.defaultGetValueSettings; + delete behavior.defaultSetValueSettings; + if (!behavior.defaultWidgetActionSettings) { + behavior.defaultWidgetActionSettings = mergeDeep({} as WidgetAction, defaultWidgetActionSettings); + } + break; + } + } + return behavior; +}; export const defaultScadaSymbolObjectSettings = (metadata: ScadaSymbolMetadata): ScadaSymbolObjectSettings => { const settings: ScadaSymbolObjectSettings = { @@ -373,11 +418,17 @@ export const defaultScadaSymbolObjectSettings = (metadata: ScadaSymbolMetadata): }; for (const behavior of metadata.behavior) { if (behavior.type === ScadaSymbolBehaviorType.value) { - settings.behavior[behavior.id] = defaultGetValueSettings(behavior as ScadaSymbolBehaviorValue); + settings.behavior[behavior.id] = + mergeDeep({} as GetValueSettings, + defaultGetValueSettings(behavior.valueType), (behavior as ScadaSymbolBehaviorValue).defaultGetValueSettings || {}); } else if (behavior.type === ScadaSymbolBehaviorType.action) { - settings.behavior[behavior.id] = defaultSetValueSettings(behavior as ScadaSymbolBehaviorAction); + settings.behavior[behavior.id] = + mergeDeep({} as SetValueSettings, + defaultSetValueSettings(behavior.valueType), (behavior as ScadaSymbolBehaviorAction).defaultSetValueSettings || {}); } else if (behavior.type === ScadaSymbolBehaviorType.widgetAction) { - settings.behavior[behavior.id] = defaultWidgetActionSettings(behavior); + settings.behavior[behavior.id] = + mergeDeep({} as WidgetAction, + defaultWidgetActionSettings, (behavior as ScadaSymbolBehaviorAction).defaultWidgetActionSettings || {}); } } for (const property of metadata.properties) { @@ -733,17 +784,7 @@ export class ScadaSymbolObject { private normalizeValue(value: any, type: ValueType): any { if (isUndefinedOrNull(value)) { - switch (type) { - case ValueType.STRING: - return ''; - case ValueType.INTEGER: - case ValueType.DOUBLE: - return 0; - case ValueType.BOOLEAN: - return false; - case ValueType.JSON: - return {}; - } + return defaultValueForValueType(type); } else { return value; } 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 00cabe0599..c55ccfd2b5 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 @@ -141,6 +141,10 @@ import { import { TypeValuePanelComponent } from '@home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component'; +import { TruncateWithTooltipDirective } from '@shared/directives/truncate-with-tooltip.directive'; +import { + ModbusRpcParametersComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component'; import { ScadaSymbolWidgetComponent } from '@home/components/widget/lib/scada/scada-symbol-widget.component'; @NgModule({ @@ -229,6 +233,8 @@ import { ScadaSymbolWidgetComponent } from '@home/components/widget/lib/scada/sc KeyValueIsNotEmptyPipe, ModbusBasicConfigComponent, EllipsisChipListDirective, + TruncateWithTooltipDirective, + ModbusRpcParametersComponent, ], exports: [ EntitiesTableWidgetComponent, 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 f4c2eb1fa8..544a70e9fd 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 @@ -150,6 +150,10 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe @coerceBoolean() isAdd = false; + @Input() + @coerceBoolean() + scada = false; + @Input() disabled: boolean; widgetConfigMode = WidgetConfigMode.advanced; @@ -341,12 +345,14 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe value: 'actions' } ); - this.headerOptions.push( - { - name: this.translate.instant('widget-config.mobile'), - value: 'mobile' - } - ); + if (!this.scada) { + this.headerOptions.push( + { + name: this.translate.instant('widget-config.mobile'), + value: 'mobile' + } + ); + } if (!this.selectedOption || !this.headerOptions.find(o => o.value === this.selectedOption)) { this.selectedOption = this.headerOptions[0].value; } diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.html index 749b6cf362..96d8788a38 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.html @@ -70,11 +70,6 @@
-
-
scada.behavior.default-value
- -
scada.behavior.true-label
@@ -95,34 +90,41 @@
+
+
scada.behavior.default-settings
+ + +
-
-
-
{{ 'scada.behavior.default-payload' | translate }}
- - {{ 'widgets.value-action.converter-value' | translate }} - {{ 'widgets.value-action.converter-constant' | translate }} - {{ 'widgets.value-action.converter-function' | translate }} - {{ 'widgets.value-action.converter-none' | translate }} - -
- - - - +
+
scada.behavior.default-settings
+ + +
+ + +
+
scada.behavior.default-settings
+ +
diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.ts index 500cd4a454..f7ce9c7a0e 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-panel.component.ts @@ -19,14 +19,19 @@ import { TbPopoverComponent } from '@shared/components/popover.component'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { merge } from 'rxjs'; import { + defaultGetValueSettings, defaultSetValueSettings, defaultWidgetActionSettings, ScadaSymbolBehavior, ScadaSymbolBehaviorType, scadaSymbolBehaviorTypes, scadaSymbolBehaviorTypeTranslations } from '@app/modules/home/components/widget/lib/scada/scada-symbol.models'; import { ValueType, valueTypesMap } from '@shared/models/constants'; -import { ValueToDataType } from '@shared/models/action-widget-settings.models'; +import { GetValueSettings, SetValueSettings, ValueToDataType } from '@shared/models/action-widget-settings.models'; import { WidgetService } from '@core/http/widget.service'; +import { mergeDeep } from '@core/utils'; +import { WidgetAction, widgetType } from '@shared/models/widget.models'; +import { IAliasController } from '@core/api/widget-api.models'; +import { WidgetActionCallbacks } from '@home/components/widget/action/manage-widget-actions.component.models'; @Component({ selector: 'tb-scada-symbol-behavior-panel', @@ -36,6 +41,8 @@ import { WidgetService } from '@core/http/widget.service'; }) export class ScadaSymbolBehaviorPanelComponent implements OnInit { + widgetType = widgetType; + ScadaSymbolBehaviorType = ScadaSymbolBehaviorType; ValueType = ValueType; @@ -55,6 +62,12 @@ export class ScadaSymbolBehaviorPanelComponent implements OnInit { @Input() behavior: ScadaSymbolBehavior; + @Input() + aliasController: IAliasController; + + @Input() + callbacks: WidgetActionCallbacks; + @Input() disabled: boolean; @@ -84,21 +97,19 @@ export class ScadaSymbolBehaviorPanelComponent implements OnInit { group: [this.behavior.group, []], type: [this.behavior.type, [Validators.required]], valueType: [this.behavior.valueType, [Validators.required]], - defaultValue: [this.behavior.defaultValue, [Validators.required]], trueLabel: [this.behavior.trueLabel, []], falseLabel: [this.behavior.falseLabel, []], stateLabel: [this.behavior.stateLabel, []], - valueToDataType: [this.behavior.valueToDataType, [Validators.required]], - constantValue: [this.behavior.constantValue, [Validators.required]], - valueToDataFunction: [this.behavior.valueToDataFunction, [Validators.required]] + defaultGetValueSettings: [this.behavior.defaultGetValueSettings, [Validators.required]], + defaultSetValueSettings: [this.behavior.defaultSetValueSettings, [Validators.required]], + defaultWidgetActionSettings: [this.behavior.defaultWidgetActionSettings, [Validators.required]] } ); if (this.disabled) { this.behaviorFormGroup.disable({emitEvent: false}); } else { merge(this.behaviorFormGroup.get('type').valueChanges, - this.behaviorFormGroup.get('valueType').valueChanges, - this.behaviorFormGroup.get('valueToDataType').valueChanges).subscribe(() => { + this.behaviorFormGroup.get('valueType').valueChanges).subscribe(() => { this.updateValidators(); }); this.updateValidators(); @@ -117,7 +128,9 @@ export class ScadaSymbolBehaviorPanelComponent implements OnInit { private updateValidators() { const type: ScadaSymbolBehaviorType = this.behaviorFormGroup.get('type').value; const valueType: ValueType = this.behaviorFormGroup.get('valueType').value; - let valueToDataType: ValueToDataType = this.behaviorFormGroup.get('valueToDataType').value; + let defaultGetValueSettingsValue = this.behaviorFormGroup.get('defaultGetValueSettings').value; + let defaultSetValueSettingsValue = this.behaviorFormGroup.get('defaultSetValueSettings').value; + let defaultWidgetActionSettingsValue = this.behaviorFormGroup.get('defaultWidgetActionSettings').value; this.behaviorFormGroup.disable({emitEvent: false}); this.behaviorFormGroup.get('id').enable({emitEvent: false}); this.behaviorFormGroup.get('name').enable({emitEvent: false}); @@ -127,30 +140,49 @@ export class ScadaSymbolBehaviorPanelComponent implements OnInit { switch (type) { case ScadaSymbolBehaviorType.value: this.behaviorFormGroup.get('valueType').enable({emitEvent: false}); - this.behaviorFormGroup.get('defaultValue').enable({emitEvent: false}); + this.behaviorFormGroup.get('defaultGetValueSettings').enable({emitEvent: false}); if (valueType === ValueType.BOOLEAN) { this.behaviorFormGroup.get('trueLabel').enable({emitEvent: false}); this.behaviorFormGroup.get('falseLabel').enable({emitEvent: false}); this.behaviorFormGroup.get('stateLabel').enable({emitEvent: false}); } + if (!defaultGetValueSettingsValue) { + defaultGetValueSettingsValue = mergeDeep({} as GetValueSettings, defaultGetValueSettings(valueType)); + this.behaviorFormGroup.get('defaultGetValueSettings').patchValue(defaultGetValueSettingsValue, {emitEvent: true}); + } + if (defaultSetValueSettingsValue) { + this.behaviorFormGroup.get('defaultSetValueSettings').patchValue(null, {emitEvent: true}); + } + if (defaultWidgetActionSettingsValue) { + this.behaviorFormGroup.get('defaultWidgetActionSettings').patchValue(null, {emitEvent: true}); + } break; case ScadaSymbolBehaviorType.action: - if (valueType === ValueType.BOOLEAN && valueToDataType === ValueToDataType.VALUE) { - this.behaviorFormGroup.patchValue({valueToDataType: ValueToDataType.CONSTANT}, {emitEvent: false}); - valueToDataType = ValueToDataType.CONSTANT; - } else if (valueType !== ValueType.BOOLEAN && valueToDataType === ValueToDataType.CONSTANT) { - this.behaviorFormGroup.patchValue({valueToDataType: ValueToDataType.VALUE}, {emitEvent: false}); - valueToDataType = ValueToDataType.VALUE; - } this.behaviorFormGroup.get('valueType').enable({emitEvent: false}); - this.behaviorFormGroup.get('valueToDataType').enable({emitEvent: false}); - if (valueToDataType === ValueToDataType.CONSTANT) { - this.behaviorFormGroup.get('constantValue').enable({emitEvent: false}); - } else if (valueToDataType === ValueToDataType.FUNCTION) { - this.behaviorFormGroup.get('valueToDataFunction').enable({emitEvent: false}); + this.behaviorFormGroup.get('defaultSetValueSettings').enable({emitEvent: false}); + if (!defaultSetValueSettingsValue) { + defaultSetValueSettingsValue = mergeDeep({} as SetValueSettings, defaultSetValueSettings(valueType)); + this.behaviorFormGroup.get('defaultSetValueSettings').patchValue(defaultSetValueSettingsValue, {emitEvent: true}); + } + if (defaultGetValueSettingsValue) { + this.behaviorFormGroup.get('defaultGetValueSettings').patchValue(null, {emitEvent: true}); + } + if (defaultWidgetActionSettingsValue) { + this.behaviorFormGroup.get('defaultWidgetActionSettings').patchValue(null, {emitEvent: true}); } break; case ScadaSymbolBehaviorType.widgetAction: + this.behaviorFormGroup.get('defaultWidgetActionSettings').enable({emitEvent: false}); + if (!defaultWidgetActionSettingsValue) { + defaultWidgetActionSettingsValue = mergeDeep({} as WidgetAction, defaultWidgetActionSettings); + this.behaviorFormGroup.get('defaultWidgetActionSettings').patchValue(defaultWidgetActionSettingsValue, {emitEvent: true}); + } + if (defaultGetValueSettingsValue) { + this.behaviorFormGroup.get('defaultGetValueSettings').patchValue(null, {emitEvent: true}); + } + if (defaultSetValueSettingsValue) { + this.behaviorFormGroup.get('defaultSetValueSettings').patchValue(null, {emitEvent: true}); + } break; } } diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component.ts index b1070d9de9..eb71f4ff9f 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component.ts @@ -43,7 +43,7 @@ import { ScadaSymbolBehavior, ScadaSymbolBehaviorType, scadaSymbolBehaviorTypes, - scadaSymbolBehaviorTypeTranslations + scadaSymbolBehaviorTypeTranslations, updateBehaviorDefaultSettings } from '@home/components/widget/lib/scada/scada-symbol.models'; import { deepClone, isUndefinedOrNull } from '@core/utils'; import { MatButton } from '@angular/material/button'; @@ -55,6 +55,8 @@ import { ValueToDataType } from '@shared/models/action-widget-settings.models'; import { ScadaSymbolBehaviorsComponent } from '@home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component'; +import { IAliasController } from '@core/api/widget-api.models'; +import { WidgetActionCallbacks } from '@home/components/widget/action/manage-widget-actions.component.models'; export const behaviorValid = (behavior: ScadaSymbolBehavior): boolean => { if (!behavior.id || !behavior.name || !behavior.type) { @@ -62,20 +64,20 @@ export const behaviorValid = (behavior: ScadaSymbolBehavior): boolean => { } switch (behavior.type) { case ScadaSymbolBehaviorType.value: - if (!behavior.valueType || isUndefinedOrNull(behavior.defaultValue)) { + if (!behavior.valueType || !behavior.defaultGetValueSettings) { return false; } break; case ScadaSymbolBehaviorType.action: - if (!behavior.valueToDataType) { + if (!behavior.defaultSetValueSettings) { return false; } - if (behavior.valueToDataType === ValueToDataType.CONSTANT - && isUndefinedOrNull(behavior.constantValue)) { + if (behavior.defaultSetValueSettings.valueToData?.type === ValueToDataType.CONSTANT + && isUndefinedOrNull(behavior.defaultSetValueSettings.valueToData?.constantValue)) { return false; } - if (behavior.valueToDataType === ValueToDataType.FUNCTION - && isUndefinedOrNull(behavior.valueToDataFunction)) { + if (behavior.defaultSetValueSettings.valueToData?.type === ValueToDataType.FUNCTION + && isUndefinedOrNull(behavior.defaultSetValueSettings.valueToData?.valueToDataFunction)) { return false; } break; @@ -120,6 +122,12 @@ export class ScadaSymbolBehaviorRowComponent implements ControlValueAccessor, On @Input() index: number; + @Input() + aliasController: IAliasController; + + @Input() + callbacks: WidgetActionCallbacks; + @Output() behaviorRemoved = new EventEmitter(); @@ -190,6 +198,8 @@ export class ScadaSymbolBehaviorRowComponent implements ControlValueAccessor, On const ctx: any = { isAdd: add, disabled: this.disabled, + aliasController: this.aliasController, + callbacks: this.callbacks, behavior: deepClone(this.modelValue) }; const scadaSymbolBehaviorPanelPopover = this.popoverService.displayPopover(trigger, this.renderer, @@ -265,13 +275,15 @@ export class ScadaSymbolBehaviorRowComponent implements ControlValueAccessor, On } private onTypeChanged(newType: ScadaSymbolBehaviorType) { - const prevType = this.modelValue.type; + const prevModel = deepClone(this.modelValue); this.modelValue = {...this.modelValue, ...{type: newType}}; + this.modelValue = updateBehaviorDefaultSettings(this.modelValue); if (!behaviorValid(this.modelValue)) { this.editBehavior(null, this.editButton, false, () => { + this.modelValue = prevModel; this.behaviorRowFormGroup.patchValue( { - type: prevType + type: prevModel.type }, {emitEvent: true} ); }); diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.html index 60dc5fc908..7cefc6af63 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.html @@ -33,6 +33,8 @@
diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.ts index c53e6031a2..0ad1e59e05 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-behaviors.component.ts @@ -35,15 +35,22 @@ import { UntypedFormGroup, Validator } from '@angular/forms'; -import { ScadaSymbolBehavior, ScadaSymbolBehaviorType } from '@home/components/widget/lib/scada/scada-symbol.models'; +import { + defaultGetValueSettings, + ScadaSymbolBehavior, + ScadaSymbolBehaviorType +} from '@home/components/widget/lib/scada/scada-symbol.models'; import { ValueType } from '@shared/models/constants'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { behaviorValid, ScadaSymbolBehaviorRowComponent } from '@home/pages/scada-symbol/metadata-components/scada-symbol-behavior-row.component'; -import { ValueToDataType } from '@shared/models/action-widget-settings.models'; +import { GetValueSettings, ValueToDataType } from '@shared/models/action-widget-settings.models'; import { TranslateService } from '@ngx-translate/core'; +import { mergeDeep } from '@core/utils'; +import { IAliasController } from '@core/api/widget-api.models'; +import { WidgetActionCallbacks } from '@home/components/widget/action/manage-widget-actions.component.models'; @Component({ selector: 'tb-scada-symbol-metadata-behaviors', @@ -71,6 +78,12 @@ export class ScadaSymbolBehaviorsComponent implements ControlValueAccessor, OnIn @ViewChildren(ScadaSymbolBehaviorRowComponent) behaviorRows: QueryList; + @Input() + aliasController: IAliasController; + + @Input() + callbacks: WidgetActionCallbacks; + @Input() disabled: boolean; @@ -181,10 +194,7 @@ export class ScadaSymbolBehaviorsComponent implements ControlValueAccessor, OnIn name: '', type: ScadaSymbolBehaviorType.value, valueType: ValueType.BOOLEAN, - defaultValue: false, - valueToDataType: ValueToDataType.CONSTANT, - constantValue: false, - valueToDataFunction: '' + defaultGetValueSettings: mergeDeep({} as GetValueSettings, defaultGetValueSettings(ValueType.BOOLEAN)) }; const behaviorsArray = this.behaviorsFormGroup.get('behaviors') as UntypedFormArray; const behaviorControl = this.fb.control(behavior, []); diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts index ecc7a507a6..d46ba364d7 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts @@ -101,13 +101,13 @@ export class ScadaSymbolMetadataTagFunctionPanelComponent implements OnInit, Aft this.tagFunctionArgs = ['ctx', 'element']; this.objectHighlightRules = scadaSymbolElementStateRenderHighlightRules; this.propertyHighlightRules = scadaSymbolElementStateRenderPropertiesHighlightRules; - this.tagFunctionHelpId = 'widget/lib/timeseries/cell_style_fn'; // TODO: + this.tagFunctionHelpId = 'scada/tag_state_render_fn'; } else if (this.tagFunctionType === 'clickAction') { this.panelTitle = 'scada.tag.on-click-action'; this.tagFunctionArgs = ['ctx', 'element', 'event']; this.objectHighlightRules = scadaSymbolClickActionHighlightRules; this.propertyHighlightRules = scadaSymbolClickActionPropertiesHighlightRules; - this.tagFunctionHelpId = 'widget/lib/timeseries/cell_style_fn'; // TODO: + this.tagFunctionHelpId = 'scada/tag_click_action_fn'; } } diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html index 573ea27af0..9e5d22fa94 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html @@ -83,7 +83,7 @@ [objectHighlightRules]="scadaSymbolGeneralStateRenderHighlightRules" [propertyHighlightRules]="scadaSymbolGeneralStateRenderPropertiesHighlightRules" [functionArgs]="['ctx', 'svg']" - helpId="widget/lib/timeseries/cell_style_fn"> + helpId="scada/symbol_state_render_fn"> @@ -101,7 +101,9 @@
+ formControlName="behavior" + [aliasController]="aliasController" + [callbacks]="callbacks">
diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts index db266f5a08..f5ecaab3d2 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts @@ -53,6 +53,8 @@ import { scadaSymbolGeneralStateRenderPropertiesHighlightRules } from '@home/pages/scada-symbol/scada-symbol-editor.models'; import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe'; +import { IAliasController } from '@core/api/widget-api.models'; +import { WidgetActionCallbacks } from '@home/components/widget/action/manage-widget-actions.component.models'; @Component({ selector: 'tb-scada-symbol-metadata', @@ -77,6 +79,12 @@ export class ScadaSymbolMetadataComponent extends PageComponent implements OnIni @ViewChild('symbolMetadataTags') symbolMetadataTags: ScadaSymbolMetadataTagsComponent; + @Input() + aliasController: IAliasController; + + @Input() + callbacks: WidgetActionCallbacks; + @Input() disabled: boolean; diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts index 5ddec8b1a9..f3caf1dbfc 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts @@ -1167,37 +1167,110 @@ export const scadaSymbolContextCompletion = (metadata: ScadaSymbolMetadata, tags description: 'Set text to element(s). Only applicable for elements of type ' + 'SVG.Text or ' + 'SVG.Tspan.', - args: [] + args: [ + { + name: 'element', + description: 'SVG element or an array of SVG elements', + type: 'Element | Array<Element>' + }, + { + name: 'text', + description: 'Text to be set', + type: 'string' + } + ] }, font: { meta: 'function', description: 'Set element(s) text font and color. Only applicable for elements of type ' + 'SVG.Text or ' + 'SVG.Tspan.', - args: [] + args: [ + { + name: 'element', + description: 'SVG element or an array of SVG elements', + type: 'Element | Array<Element>' + }, + { + name: 'font', + description: 'Font settings object used to apply text element font', + type: 'Font' + }, + { + name: 'color', + description: 'Color string used to apply text color of the element', + type: 'string' + } + ] }, disable: { meta: 'function', description: 'Disables element(s). Disabled element doesn\'t accept any user interaction. ' + 'For ex. if disabled element has click action, no click action will be performed on user click.', - args: [] + args: [ + { + name: 'element', + description: 'SVG element or an array of SVG elements', + type: 'Element | Array<Element>' + } + ] }, enable: { meta: 'function', description: 'Enables disabled element(s). Enabled element accepts user interaction. ' + 'For ex. if element has click action, click action will be performed on user click.', - args: [] + args: [ + { + name: 'element', + description: 'SVG element or an array of SVG elements', + type: 'Element | Array<Element>' + } + ] }, callAction: { meta: 'function', description: 'Invokes action specified by behavior of type "Action" found by behaviorId.', - args: [] + args: [ + { + name: 'event', + description: 'DOM event', + type: 'Event' + }, + { + name: 'behaviorId', + description: 'Id of the "Action" behavior', + type: 'string' + }, + { + name: 'value', + description: 'Optional value passed to behavior', + type: 'any', + optional: true + }, + { + name: 'observer', + description: 'Optional observer callback', + type: 'Partial<Observer<void>>', + optional: true + } + ] }, setValue: { meta: 'function', description: 'Updates value by valueId. See ctx.values for reference. ' + 'Value update triggers all render functions.', - args: [] + args: [ + { + name: 'valueId', + description: 'Id of the value to be updated', + type: 'string' + }, + { + name: 'value', + description: 'New value to be set', + type: 'any' + } + ] } } }, diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html index 54251bd8ed..6662509fa6 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html @@ -80,6 +80,8 @@