From 8bc49896eda3f2878269d3da7974c0ba8e075f5a Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 13 Apr 2018 19:32:02 +0300 Subject: [PATCH] Fixed AlarmNode, UI: Config forms for Alarm, Log and ToEmail nodes. --- .../server/actors/ActorSystemContext.java | 5 ++ .../actors/ruleChain/DefaultTbContext.java | 5 ++ .../controller/RuleChainController.java | 7 +++ .../executors/AbstractListeningExecutor.java | 59 +++++++++++++++++++ .../executors/DbCallbackExecutorService.java | 32 ++++++++++ .../service/mail/MailExecutorService.java | 31 ++-------- .../service/script/JsExecutorService.java | 30 ++-------- .../service/script/NashornJsEngine.java | 4 ++ .../src/main/resources/thingsboard.yml | 3 + .../rule/engine/api/ListeningExecutor.java | 3 +- .../rule/engine/api/TbContext.java | 2 + .../rule/engine/action/TbAlarmNode.java | 27 +++++---- .../rule/engine/action/TbLogNode.java | 4 +- .../rule/engine/mail/TbMsgToEmailNode.java | 4 +- .../static/rulenode/rulenode-core-config.js | 3 +- ui/src/app/rulechain/rulechain.controller.js | 55 ++++++++++++----- 16 files changed, 191 insertions(+), 83 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/executors/AbstractListeningExecutor.java create mode 100644 application/src/main/java/org/thingsboard/server/service/executors/DbCallbackExecutorService.java diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index 7c7747cec3..50d2530b53 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -59,6 +59,7 @@ import org.thingsboard.server.service.cluster.discovery.DiscoveryService; import org.thingsboard.server.service.cluster.routing.ClusterRoutingService; import org.thingsboard.server.service.cluster.rpc.ClusterRpcService; import org.thingsboard.server.service.component.ComponentDiscoveryService; +import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.mail.MailExecutorService; import org.thingsboard.server.service.script.JsExecutorService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; @@ -173,6 +174,10 @@ public class ActorSystemContext { @Getter private MailExecutorService mailExecutor; + @Autowired + @Getter + private DbCallbackExecutorService dbCallbackExecutor; + @Autowired @Getter private MailService mailService; diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index 4ff75bf2a3..8ffd378da7 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -137,6 +137,11 @@ class DefaultTbContext implements TbContext { return mainCtx.getMailExecutor(); } + @Override + public ListeningExecutor getDbCallbackExecutor() { + return mainCtx.getDbCallbackExecutor(); + } + @Override public ScriptEngine createJsScriptEngine(String script, String functionName, String... argNames) { return new NashornJsEngine(script, functionName, argNames); diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index f20ff8f915..48c9cd5342 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -253,6 +253,13 @@ public class RuleChainController extends BaseController { Set states = engine.executeSwitch(inMsg); output = objectMapper.writeValueAsString(states); break; + case "json": + JsonNode json = engine.executeJson(inMsg); + output = objectMapper.writeValueAsString(json); + break; + case "string": + output = engine.executeToString(inMsg); + break; default: throw new IllegalArgumentException("Unsupported script type: " + scriptType); } diff --git a/application/src/main/java/org/thingsboard/server/service/executors/AbstractListeningExecutor.java b/application/src/main/java/org/thingsboard/server/service/executors/AbstractListeningExecutor.java new file mode 100644 index 0000000000..91ef9de66f --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/executors/AbstractListeningExecutor.java @@ -0,0 +1,59 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.executors; + +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import org.thingsboard.rule.engine.api.ListeningExecutor; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; + +/** + * Created by igor on 4/13/18. + */ +public abstract class AbstractListeningExecutor implements ListeningExecutor { + + private ListeningExecutorService service; + + @PostConstruct + public void init() { + this.service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(getThreadPollSize())); + } + + @PreDestroy + public void destroy() { + if (this.service != null) { + this.service.shutdown(); + } + } + + @Override + public ListenableFuture executeAsync(Callable task) { + return service.submit(task); + } + + @Override + public void execute(Runnable command) { + service.execute(command); + } + + protected abstract int getThreadPollSize(); + +} diff --git a/application/src/main/java/org/thingsboard/server/service/executors/DbCallbackExecutorService.java b/application/src/main/java/org/thingsboard/server/service/executors/DbCallbackExecutorService.java new file mode 100644 index 0000000000..2eec3ed234 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/executors/DbCallbackExecutorService.java @@ -0,0 +1,32 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.executors; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class DbCallbackExecutorService extends AbstractListeningExecutor { + + @Value("${actors.rule.db_callback_thread_pool_size}") + private int dbCallbackExecutorThreadPoolSize; + + @Override + protected int getThreadPollSize() { + return dbCallbackExecutorThreadPoolSize; + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/mail/MailExecutorService.java b/application/src/main/java/org/thingsboard/server/service/mail/MailExecutorService.java index 97c860694c..e8caab62a6 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/MailExecutorService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/MailExecutorService.java @@ -15,40 +15,19 @@ */ package org.thingsboard.server.service.mail; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.thingsboard.rule.engine.api.ListeningExecutor; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; +import org.thingsboard.server.service.executors.AbstractListeningExecutor; @Component -public class MailExecutorService implements ListeningExecutor { +public class MailExecutorService extends AbstractListeningExecutor { @Value("${actors.rule.mail_thread_pool_size}") private int mailExecutorThreadPoolSize; - private ListeningExecutorService service; - - @PostConstruct - public void init() { - this.service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(mailExecutorThreadPoolSize)); - } - - @PreDestroy - public void destroy() { - if (this.service != null) { - this.service.shutdown(); - } - } - @Override - public ListenableFuture executeAsync(Callable task) { - return service.submit(task); + protected int getThreadPollSize() { + return mailExecutorThreadPoolSize; } + } diff --git a/application/src/main/java/org/thingsboard/server/service/script/JsExecutorService.java b/application/src/main/java/org/thingsboard/server/service/script/JsExecutorService.java index 9d110d13f7..c60f45550f 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/JsExecutorService.java +++ b/application/src/main/java/org/thingsboard/server/service/script/JsExecutorService.java @@ -15,41 +15,19 @@ */ package org.thingsboard.server.service.script; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.thingsboard.rule.engine.api.ListeningExecutor; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; +import org.thingsboard.server.service.executors.AbstractListeningExecutor; @Component -public class JsExecutorService implements ListeningExecutor{ +public class JsExecutorService extends AbstractListeningExecutor { @Value("${actors.rule.js_thread_pool_size}") private int jsExecutorThreadPoolSize; - private ListeningExecutorService service; - - @PostConstruct - public void init() { - this.service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(jsExecutorThreadPoolSize)); - } - - @PreDestroy - public void destroy() { - if (this.service != null) { - this.service.shutdown(); - } - } - @Override - public ListenableFuture executeAsync(Callable task) { - return service.submit(task); + protected int getThreadPollSize() { + return jsExecutorThreadPoolSize; } } diff --git a/application/src/main/java/org/thingsboard/server/service/script/NashornJsEngine.java b/application/src/main/java/org/thingsboard/server/service/script/NashornJsEngine.java index b9583f04db..d68f6fed29 100644 --- a/application/src/main/java/org/thingsboard/server/service/script/NashornJsEngine.java +++ b/application/src/main/java/org/thingsboard/server/service/script/NashornJsEngine.java @@ -153,6 +153,10 @@ public class NashornJsEngine implements org.thingsboard.rule.engine.api.ScriptEn @Override public String executeToString(TbMsg msg) throws ScriptException { JsonNode result = executeScript(msg); + if (!result.isTextual()) { + log.warn("Wrong result type: {}", result.getNodeType()); + throw new ScriptException("Wrong result type: " + result.getNodeType()); + } return result.asText(); } diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index b5011e2a20..a9e47de87e 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -219,8 +219,11 @@ actors: termination.delay: "${ACTORS_RULE_TERMINATION_DELAY:30000}" # Errors for particular actor are persisted once per specified amount of milliseconds error_persist_frequency: "${ACTORS_RULE_ERROR_FREQUENCY:3000}" + # Specify thread pool size for database request callbacks executor service + db_callback_thread_pool_size: "${ACTORS_RULE_DB_CALLBACK_THREAD_POOL_SIZE:1}" # Specify thread pool size for javascript executor service js_thread_pool_size: "${ACTORS_RULE_JS_THREAD_POOL_SIZE:10}" + # Specify thread pool size for mail sender executor service mail_thread_pool_size: "${ACTORS_RULE_MAIL_THREAD_POOL_SIZE:10}" chain: # Errors for particular actor are persisted once per specified amount of milliseconds diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/ListeningExecutor.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/ListeningExecutor.java index 5420f7ff6f..9356be96fc 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/ListeningExecutor.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/ListeningExecutor.java @@ -18,8 +18,9 @@ package org.thingsboard.rule.engine.api; import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Callable; +import java.util.concurrent.Executor; -public interface ListeningExecutor { +public interface ListeningExecutor extends Executor { ListenableFuture executeAsync(Callable task); diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java index fcc9b5c03c..6038e6d84f 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java @@ -88,6 +88,8 @@ public interface TbContext { ListeningExecutor getMailExecutor(); + ListeningExecutor getDbCallbackExecutor(); + MailService getMailService(); ScriptEngine createJsScriptEngine(String script, String functionName, String... argNames); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAlarmNode.java index 97d54774ce..0549e6af23 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAlarmNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAlarmNode.java @@ -1,12 +1,12 @@ /** * Copyright © 2016-2018 The Thingsboard Authors - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -32,6 +32,8 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; +import java.util.concurrent.ExecutorService; + import static org.thingsboard.rule.engine.DonAsynchron.withCallback; @Slf4j @@ -47,7 +49,8 @@ import static org.thingsboard.rule.engine.DonAsynchron.withCallback; "If alarm was not created, original message is returned. Otherwise new Message returned with type 'ALARM', Alarm object in 'msg' property and 'matadata' will contains one of those properties 'isNewAlarm/isExistingAlarm/isClearedAlarm' " + "Message payload can be accessed via msg property. For example 'temperature = ' + msg.temperature ;" + "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;", - uiResources = {"static/rulenode/rulenode-core-config.js"}) + uiResources = {"static/rulenode/rulenode-core-config.js"}, + configDirective = "tbActionNodeAlarmConfig") public class TbAlarmNode implements TbNode { @@ -81,7 +84,7 @@ public class TbAlarmNode implements TbNode { } else { return checkForClearIfExist(ctx, msg); } - }); + }, ctx.getDbCallbackExecutor()); withCallback(transform, alarmResult -> { @@ -107,7 +110,7 @@ public class TbAlarmNode implements TbNode { } else { return updateAlarm(ctx, msg, a); } - }); + }, ctx.getDbCallbackExecutor()); } private ListenableFuture checkForClearIfExist(TbContext ctx, TbMsg msg) { @@ -117,12 +120,14 @@ public class TbAlarmNode implements TbNode { return clearAlarm(ctx, msg, a); } return Futures.immediateFuture(new AlarmResult(false, false, false, null)); - }); + }, ctx.getDbCallbackExecutor()); } private ListenableFuture createNewAlarm(TbContext ctx, TbMsg msg) { - ListenableFuture asyncAlarm = Futures.transform(buildAlarmDetails(ctx, msg), (Function) details -> buildAlarm(msg, details, ctx.getTenantId())); - ListenableFuture asyncCreated = Futures.transform(asyncAlarm, (Function) alarm -> ctx.getAlarmService().createOrUpdateAlarm(alarm)); + ListenableFuture asyncAlarm = Futures.transform(buildAlarmDetails(ctx, msg), + (Function) details -> buildAlarm(msg, details, ctx.getTenantId())); + ListenableFuture asyncCreated = Futures.transform(asyncAlarm, + (Function) alarm -> ctx.getAlarmService().createOrUpdateAlarm(alarm), ctx.getDbCallbackExecutor()); return Futures.transform(asyncCreated, (Function) alarm -> new AlarmResult(true, false, false, alarm)); } @@ -133,7 +138,7 @@ public class TbAlarmNode implements TbNode { alarm.setDetails(details); alarm.setEndTs(System.currentTimeMillis()); return ctx.getAlarmService().createOrUpdateAlarm(alarm); - }); + }, ctx.getDbCallbackExecutor()); return Futures.transform(asyncUpdated, (Function) a -> new AlarmResult(false, true, false, a)); } 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 8dbbf089ff..3cd299dcc6 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 @@ -31,7 +31,9 @@ import static org.thingsboard.rule.engine.DonAsynchron.withCallback; nodeDescription = "Log incoming messages using JS script for transformation Message into String", nodeDetails = "Transform incoming Message with configured JS condition to String and log final value. " + "Message payload can be accessed via msg property. For example 'temperature = ' + msg.temperature ;" + - "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;") + "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;", + uiResources = {"static/rulenode/rulenode-core-config.js"}, + configDirective = "tbActionNodeLogConfig") public class TbLogNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java index a35e694bde..cae2058417 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java @@ -40,7 +40,9 @@ import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE; configClazz = TbMsgToEmailNodeConfiguration.class, nodeDescription = "Change Message Originator To Tenant/Customer/Related Entity", nodeDetails = "Related Entity found using configured relation direction and Relation Type. " + - "If multiple Related Entities are found, only first Entity is used as new Originator, other entities are discarded. ") + "If multiple Related Entities are found, only first Entity is used as new Originator, other entities are discarded. ", + uiResources = {"static/rulenode/rulenode-core-config.js"}, + configDirective = "tbTransformationNodeToEmailConfig") public class TbMsgToEmailNode implements TbNode { private static final ObjectMapper MAPPER = new ObjectMapper(); 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 85e7f782fa..edf7ddcff8 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,2 +1,3 @@ -!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),r=e[t[0]];return function(e,t,a){r.apply(this,[e,t,a].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(34)},function(e,t){},1,1,function(e,t){e.exports="

tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
{{ 'tb.rulenode.test-generator-function' | translate }}
"},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},6,function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-filter-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-switch-function' | translate }}
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
{{ \'tb.rulenode.clone-message\' | translate }}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-transformer-function' | translate }}
{{ 'tb.rulenode.clone-message' | translate }}
"},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n,r){var a=function(a,i,l,s){var u=o.default;i.html(u),a.types=n,a.originator=null,a.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(a.configuration)}),s.$render=function(){a.configuration=s.$viewValue,a.configuration.originatorId&&a.configuration.originatorType?a.originator={id:a.configuration.originatorId,entityType:a.configuration.originatorType}:a.originator=null,a.$watch("originator",function(e,t){angular.equals(e,t)||(a.originator?(s.$viewValue.originatorId=a.originator.id,s.$viewValue.originatorType=a.originator.entityType):(s.$viewValue.originatorId=null,s.$viewValue.originatorType=null))},!0)},a.testScript=function(e){var n=angular.copy(a.configuration.jsScript),i={temperature:22.4,humidity:78},o={sensorType:"temperature"};r.testNodeScript(e,n,"generate",t.instant("tb.rulenode.generator")+"","Generate",["prevMsg","prevMetadata","prevMsgType"],i,o,"DebugMsg").then(function(e){a.configuration.jsScript=e,s.$setDirty()})},e(i.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{},link:a}}a.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a,n(1);var i=n(4),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(19),i=r(a),o=n(17),l=r(o);t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTelemetryConfig",i.default).directive("tbActionNodeGeneratorConfig",l.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(5),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(6),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(22),i=r(a),o=n(23),l=r(o),s=n(20),u=r(s),d=n(24),c=r(d);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",i.default).directive("tbEnrichmentNodeRelatedAttributesConfig",l.default).directive("tbEnrichmentNodeCustomerAttributesConfig",u.default).directive("tbEnrichmentNodeTenantAttributesConfig",c.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(7),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(8),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(9),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(27),i=r(a),o=n(26),l=r(o),s=n(28),u=r(s);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",i.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),a.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),a.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=a,t.removeKeyVal=i,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||a.$setViewValue(t.query)}),a.$render=function(){if(a.$viewValue){var e=a.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(13),o=r(i);n(3)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||i.$setViewValue(n.query)}),i.$render=function(){n.query=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(14),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(15),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(31),i=r(a),o=n(33),l=r(o);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",i.default).directive("tbTransformationNodeScriptConfig",l.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){var s=o.default;a.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var a=angular.copy(r.configuration.jsScript),i={temperature:22.4,humidity:78},o={sensorType:"temperature"};n.testNodeScript(e,a,"update",t.instant("tb.rulenode.transformer")+"","Transform",["msg","metadata","msgType"],i,o,"POST_TELEMETRY").then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{},link:r}}a.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(16),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(37),i=r(a),o=n(25),l=r(o),s=n(21),u=r(s),d=n(32),c=r(d),m=n(18),g=r(m),f=n(30),p=r(f),b=n(29),v=r(b),y=n(36),h=r(y);t.default=angular.module("thingsboard.ruleChain.config",[i.default,l.default,u.default,c.default,g.default]).directive("tbRelationsQueryConfig",p.default).directive("tbKvMapConfig",v.default).config(h.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","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","latest-timeseries":"Latest timeseries","relations-query":"Relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","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"},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};angular.merge(e.en_US,t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){(0,o.default)(t);for(var n in t){var r=t[n];e.translations(n,r)}}a.$inject=["$translateProvider","locales"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(35),o=r(i)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{messageType:{POST_ATTRIBUTES:{name:"Post attributes",value:"POST_ATTRIBUTES"},POST_TELEMETRY:{name:"Post telemetry",value:"POST_TELEMETRY"},RPC_REQUEST:{name:"RPC Request",value:"RPC_REQUEST"}},originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}}}).name}])); +!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),r=e[t[0]];return function(e,t,a){r.apply(this,[e,t,a].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(40)},function(e,t){},1,1,function(e,t){e.exports="
{{ 'tb.rulenode.test-condition-function' | translate }}
{{ 'tb.rulenode.test-condition-function' | translate }}
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
{{ severity.name | translate}}
tb.rulenode.alarm-severity-required
{{ 'tb.rulenode.propagate' | translate }}
"},function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
{{ 'tb.rulenode.test-generator-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-to-string-function' | translate }}
"},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},8,function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-filter-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-switch-function' | translate }}
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
{{ \'tb.rulenode.clone-message\' | translate }}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-transformer-function' | translate }}
{{ 'tb.rulenode.clone-message' | translate }}
"},function(e,t){e.exports="
tb.rulenode.from-template-required
tb.rulenode.to-template-required
tb.rulenode.subject-template-required
tb.rulenode.body-template-required
"},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n,r){var a=function(a,i,l,s){var u=o.default;i.html(u),a.types=n,a.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(a.configuration)}),s.$render=function(){a.configuration=s.$viewValue},a.testConditionJs=function(e,n){var i=angular.copy(n?a.configuration.createConditionJs:a.configuration.clearConditionJs),o={temperature:22.4,humidity:78},l={sensorType:"temperature"};r.testNodeScript(e,i,"filter",t.instant("tb.rulenode.condition")+"",n?"isAlarm":"isCleared",["msg","metadata","msgType"],o,l,"POST_TELEMETRY").then(function(e){n?a.configuration.createConditionJs=e:a.configuration.clearConditionJs=e,s.$setDirty()})},a.testDetailsBuildJs=function(e){var n=angular.copy(a.configuration.alarmDetailsBuildJs),i={temperature:22.4,humidity:78},o={sensorType:"temperature"};r.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],i,o,"POST_TELEMETRY").then(function(e){a.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(i.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{},link:a}}a.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(4),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n,r){var a=function(a,i,l,s){var u=o.default;i.html(u),a.types=n,a.originator=null,a.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(a.configuration)}),s.$render=function(){a.configuration=s.$viewValue,a.configuration.originatorId&&a.configuration.originatorType?a.originator={id:a.configuration.originatorId,entityType:a.configuration.originatorType}:a.originator=null,a.$watch("originator",function(e,t){angular.equals(e,t)||(a.originator?(s.$viewValue.originatorId=a.originator.id,s.$viewValue.originatorType=a.originator.entityType):(s.$viewValue.originatorId=null,s.$viewValue.originatorType=null))},!0)},a.testScript=function(e){var n=angular.copy(a.configuration.jsScript),i={temperature:22.4,humidity:78},o={sensorType:"temperature"};r.testNodeScript(e,n,"generate",t.instant("tb.rulenode.generator")+"","Generate",["prevMsg","prevMetadata","prevMsgType"],i,o,"DebugMsg").then(function(e){a.configuration.jsScript=e,s.$setDirty()})},e(i.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{},link:a}}a.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a,n(1);var i=n(5),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(24),i=r(a),o=n(21),l=r(o),s=n(20),u=r(s),d=n(23),c=r(d);t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTelemetryConfig",i.default).directive("tbActionNodeGeneratorConfig",l.default).directive("tbActionNodeAlarmConfig",u.default).directive("tbActionNodeLogConfig",c.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){var s=o.default;a.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var a=angular.copy(r.configuration.jsScript),i={temperature:22.4,humidity:78},o={sensorType:"temperature"};n.testNodeScript(e,a,"string",t.instant("tb.rulenode.to-string")+"","ToString",["msg","metadata","msgType"],i,o,"POST_TELEMETRY").then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{},link:r}}a.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(6),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(7),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(8),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(27),i=r(a),o=n(28),l=r(o),s=n(25),u=r(s),d=n(29),c=r(d);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",i.default).directive("tbEnrichmentNodeRelatedAttributesConfig",l.default).directive("tbEnrichmentNodeCustomerAttributesConfig",u.default).directive("tbEnrichmentNodeTenantAttributesConfig",c.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(9),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(10),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(11),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(32),i=r(a),o=n(31),l=r(o),s=n(33),u=r(s);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",i.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),a.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),a.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=a,t.removeKeyVal=i,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||a.$setViewValue(t.query)}),a.$render=function(){if(a.$viewValue){var e=a.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(15),o=r(i);n(3)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||i.$setViewValue(n.query)}),i.$render=function(){n.query=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(16),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(17),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(36),i=r(a),o=n(38),l=r(o),s=n(39),u=r(s);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",i.default).directive("tbTransformationNodeScriptConfig",l.default).directive("tbTransformationNodeToEmailConfig",u.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){var s=o.default;a.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var a=angular.copy(r.configuration.jsScript),i={temperature:22.4,humidity:78},o={sensorType:"temperature"};n.testNodeScript(e,a,"update",t.instant("tb.rulenode.transformer")+"","Transform",["msg","metadata","msgType"],i,o,"POST_TELEMETRY").then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{},link:r}}a.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(18),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(19),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{ +default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(43),i=r(a),o=n(30),l=r(o),s=n(26),u=r(s),d=n(37),c=r(d),m=n(22),g=r(m),f=n(35),p=r(f),b=n(34),v=r(b),y=n(42),T=r(y);t.default=angular.module("thingsboard.ruleChain.config",[i.default,l.default,u.default,c.default,g.default]).directive("tbRelationsQueryConfig",p.default).directive("tbKvMapConfig",v.default).config(T.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","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","latest-timeseries":"Latest timeseries","relations-query":"Relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","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","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required",propagate:"Propagate",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","to-template":"To Template","to-template-required":"To Template is required","cc-template":"Cc Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","body-template":"Body Template","body-template-required":"Body Template is required"},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};angular.merge(e.en_US,t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){(0,o.default)(t);for(var n in t){var r=t[n];e.translations(n,r)}}a.$inject=["$translateProvider","locales"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(41),o=r(i)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{messageType:{POST_ATTRIBUTES:{name:"Post attributes",value:"POST_ATTRIBUTES"},POST_TELEMETRY:{name:"Post telemetry",value:"POST_TELEMETRY"},RPC_REQUEST:{name:"RPC Request",value:"RPC_REQUEST"}},originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}}}).name}])); //# sourceMappingURL=rulenode-core-config.js.map \ No newline at end of file diff --git a/ui/src/app/rulechain/rulechain.controller.js b/ui/src/app/rulechain/rulechain.controller.js index c24f9c73f6..7358b44a28 100644 --- a/ui/src/app/rulechain/rulechain.controller.js +++ b/ui/src/app/rulechain/rulechain.controller.js @@ -62,6 +62,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time vm.isEditingRuleNodeLink = false; vm.isLibraryOpen = true; + vm.enableHotKeys = true; Object.defineProperty(vm, 'isLibraryOpenReadonly', { get: function() { return vm.isLibraryOpen }, @@ -327,8 +328,10 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time description: $translate.instant('rulenode.select-all-objects'), allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { - event.preventDefault(); - vm.modelservice.selectAll(); + if (vm.enableHotKeys) { + event.preventDefault(); + vm.modelservice.selectAll(); + } } }) .add({ @@ -336,8 +339,10 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time description: $translate.instant('rulenode.copy-selected'), allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { - event.preventDefault(); - copyRuleNodes(); + if (vm.enableHotKeys) { + event.preventDefault(); + copyRuleNodes(); + } } }) .add({ @@ -345,9 +350,11 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time description: $translate.instant('action.paste'), allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { - event.preventDefault(); - if (itembuffer.hasRuleNodes()) { - pasteRuleNodes(); + if (vm.enableHotKeys) { + event.preventDefault(); + if (itembuffer.hasRuleNodes()) { + pasteRuleNodes(); + } } } }) @@ -356,9 +363,11 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time description: $translate.instant('rulenode.deselect-all-objects'), allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { - event.preventDefault(); - event.stopPropagation(); - vm.modelservice.deselectAll(); + if (vm.enableHotKeys) { + event.preventDefault(); + event.stopPropagation(); + vm.modelservice.deselectAll(); + } } }) .add({ @@ -366,8 +375,10 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time description: $translate.instant('action.apply'), allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { - event.preventDefault(); - vm.saveRuleChain(); + if (vm.enableHotKeys) { + event.preventDefault(); + vm.saveRuleChain(); + } } }) .add({ @@ -375,8 +386,10 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time description: $translate.instant('action.decline-changes'), allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { - event.preventDefault(); - vm.revertRuleChain(); + if (vm.enableHotKeys) { + event.preventDefault(); + vm.revertRuleChain(); + } } }) .add({ @@ -384,8 +397,10 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time description: $translate.instant('rulenode.delete-selected-objects'), allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { - event.preventDefault(); - vm.modelservice.deleteSelected(); + if (vm.enableHotKeys) { + event.preventDefault(); + vm.modelservice.deleteSelected(); + } } }) } @@ -574,6 +589,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time $scope.$watch(function() { return vm.isEditingRuleNode || vm.isEditingRuleNodeLink; }, (val) => { + vm.enableHotKeys = !val; updateErrorTooltips(val); }); @@ -605,12 +621,15 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time } } else { var labels = ruleChainService.getRuleNodeSupportedLinks(sourceNode.component); + vm.enableHotKeys = false; addRuleNodeLink(event, edge, labels).then( (link) => { deferred.resolve(link); + vm.enableHotKeys = true; }, () => { deferred.reject(); + vm.enableHotKeys = true; } ); } @@ -1159,6 +1178,8 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time var ruleChainId = vm.ruleChain.id ? vm.ruleChain.id.id : null; + vm.enableHotKeys = false; + $mdDialog.show({ controller: 'AddRuleNodeController', controllerAs: 'vm', @@ -1188,7 +1209,9 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time } vm.ruleChainModel.nodes.push(ruleNode); updateRuleNodesHighlight(); + vm.enableHotKeys = true; }, function () { + vm.enableHotKeys = true; }); }