thingsboard-developers
Changes
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java 4(+2 -2)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeConfiguration.java 2(+1 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java 27(+5 -22)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeConfiguration.java 8(+2 -6)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java 4(+3 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeConfiguration.java 2(+1 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java 18(+12 -6)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java 2(+1 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java 2(+1 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java 2(+1 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java 2(+1 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java 4(+2 -2)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java 2(+1 -1)
rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.css 2(+2 -0)
rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js 2(+1 -1)
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java 14(+7 -7)
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java 52(+9 -43)
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java 6(+3 -3)
ui/server.js 1(+0 -1)
ui/src/app/locale/locale.constant.js 1(+1 -0)
ui/src/app/rulechain/rulechain.tpl.html 27(+16 -11)
ui/src/app/rulechain/rulenode-fieldset.tpl.html 35(+14 -21)
Details
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
index c684b20..eb8941c 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
@@ -35,7 +35,7 @@ import static org.thingsboard.rule.engine.DonAsynchron.withCallback;
nodeDetails = "Evaluate incoming Message with configured JS condition. " +
"If <b>True</b> - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used." +
"Message payload can be accessed via <code>msg</code> property. For example <code>msg.temperature < 10;</code>" +
- "Message metadata can be accessed via <code>meta</code> property. For example <code>meta.customerName === 'John';</code>",
+ "Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code>",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeScriptConfig")
@@ -47,7 +47,7 @@ public class TbJsFilterNode implements TbNode {
@Override
public void init(TbNodeConfiguration configuration, TbNodeState state) throws TbNodeException {
this.config = TbNodeUtils.convert(configuration, TbJsFilterNodeConfiguration.class);
- this.jsEngine = new NashornJsEngine(config.getJsScript());
+ this.jsEngine = new NashornJsEngine(config.getJsScript(), "Filter");
}
@Override
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeConfiguration.java
index 3b19c7c..2d776ce 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeConfiguration.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeConfiguration.java
@@ -26,7 +26,7 @@ public class TbJsFilterNodeConfiguration implements NodeConfiguration {
@Override
public TbJsFilterNodeConfiguration defaultConfiguration() {
TbJsFilterNodeConfiguration configuration = new TbJsFilterNodeConfiguration();
- configuration.setJsScript("msg.passed < 15 && msg.name === 'Vit' && meta.temp == 10 && msg.bigObj.prop == 42;");
+ configuration.setJsScript("return msg.passed < 15 && msg.name === 'Vit' && metadata.temp == 10 && msg.bigObj.prop == 42;");
return configuration;
}
}
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
index c1236a4..98f0ebc 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
@@ -36,7 +36,9 @@ import static org.thingsboard.rule.engine.DonAsynchron.withCallback;
nodeDetails = "Node executes configured JS script. Script should return array of next Chain names where Message should be routed. " +
"If Array is empty - message not routed to next Node. " +
"Message payload can be accessed via <code>msg</code> property. For example <code>msg.temperature < 10;</code> " +
- "Message metadata can be accessed via <code>meta</code> property. For example <code>meta.customerName === 'John';</code>")
+ "Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code>",
+ uiResources = {"static/rulenode/rulenode-core-config.js"},
+ configDirective = "tbFilterNodeSwitchConfig")
public class TbJsSwitchNode implements TbNode {
private TbJsSwitchNodeConfiguration config;
@@ -45,22 +47,11 @@ public class TbJsSwitchNode implements TbNode {
@Override
public void init(TbNodeConfiguration configuration, TbNodeState state) throws TbNodeException {
this.config = TbNodeUtils.convert(configuration, TbJsSwitchNodeConfiguration.class);
- if (config.getAllowedRelations().size() < 1) {
- String message = "Switch node should have at least 1 relation";
- log.error(message);
- throw new IllegalStateException(message);
- }
- if (!config.isRouteToAllWithNoCheck()) {
- this.jsEngine = new NashornJsEngine(config.getJsScript());
- }
+ this.jsEngine = new NashornJsEngine(config.getJsScript(), "Switch");
}
@Override
public void onMsg(TbContext ctx, TbMsg msg) {
- if (config.isRouteToAllWithNoCheck()) {
- ctx.tellNext(msg, config.getAllowedRelations());
- return;
- }
ListeningExecutor jsExecutor = ctx.getJsExecutor();
withCallback(jsExecutor.executeAsync(() -> jsEngine.executeSwitch(toBindings(msg))),
result -> processSwitch(ctx, msg, result),
@@ -68,15 +59,7 @@ public class TbJsSwitchNode implements TbNode {
}
private void processSwitch(TbContext ctx, TbMsg msg, Set<String> nextRelations) {
- if (validateRelations(nextRelations)) {
- ctx.tellNext(msg, nextRelations);
- } else {
- ctx.tellError(msg, new IllegalStateException("Unsupported relation for switch " + nextRelations));
- }
- }
-
- private boolean validateRelations(Set<String> nextRelations) {
- return config.getAllowedRelations().containsAll(nextRelations);
+ ctx.tellNext(msg, nextRelations);
}
private Bindings toBindings(TbMsg msg) {
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeConfiguration.java
index b354c71..3a4856c 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeConfiguration.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeConfiguration.java
@@ -25,19 +25,15 @@ import java.util.Set;
public class TbJsSwitchNodeConfiguration implements NodeConfiguration {
private String jsScript;
- private Set<String> allowedRelations;
- private boolean routeToAllWithNoCheck;
@Override
public TbJsSwitchNodeConfiguration defaultConfiguration() {
TbJsSwitchNodeConfiguration configuration = new TbJsSwitchNodeConfiguration();
- configuration.setJsScript("function nextRelation(meta, msg) {\n" +
+ configuration.setJsScript("function nextRelation(metadata, msg) {\n" +
" return ['one','nine'];" +
"};\n" +
"\n" +
- "nextRelation(meta, msg);");
- configuration.setAllowedRelations(Sets.newHashSet("one", "two"));
- configuration.setRouteToAllWithNoCheck(false);
+ "return nextRelation(metadata, msg);");
return configuration;
}
}
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java
index 3a86c25..8d72a7b 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java
@@ -31,7 +31,9 @@ import org.thingsboard.server.common.msg.TbMsg;
configClazz = TbMsgTypeFilterNodeConfiguration.class,
nodeDescription = "Filter incoming messages by Message Type",
nodeDetails = "Evaluate incoming Message with configured JS condition. " +
- "If incoming MessageType is expected - send Message via <b>Success</b> chain, otherwise <b>Failure</b> chain is used.")
+ "If incoming MessageType is expected - send Message via <b>Success</b> chain, otherwise <b>Failure</b> chain is used.",
+ uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"},
+ configDirective = "tbFilterNodeMessageTypeConfig")
public class TbMsgTypeFilterNode implements TbNode {
TbMsgTypeFilterNodeConfiguration config;
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeConfiguration.java
index a2e1b17..aafd2ed 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeConfiguration.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeConfiguration.java
@@ -33,7 +33,7 @@ public class TbMsgTypeFilterNodeConfiguration implements NodeConfiguration {
@Override
public TbMsgTypeFilterNodeConfiguration defaultConfiguration() {
TbMsgTypeFilterNodeConfiguration configuration = new TbMsgTypeFilterNodeConfiguration();
- configuration.setMessageTypes(Arrays.asList("GET_ATTRIBUTES","POST_ATTRIBUTES","POST_TELEMETRY","RPC_REQUEST"));
+ configuration.setMessageTypes(Arrays.asList("POST_ATTRIBUTES","POST_TELEMETRY","RPC_REQUEST"));
return configuration;
}
}
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java
index 082535f..a4add40 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java
@@ -34,14 +34,20 @@ import java.util.Set;
@Slf4j
public class NashornJsEngine {
- public static final String METADATA = "meta";
+ public static final String METADATA = "metadata";
public static final String DATA = "msg";
+
+ private static final String JS_WRAPPER_PREFIX_TEMPLATE = "function %s(msg, metadata) { ";
+ private static final String JS_WRAPPER_SUFFIX_TEMPLATE = "}\n %s(msg, metadata);";
+
private static NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
private CompiledScript engine;
- public NashornJsEngine(String script) {
- engine = compileScript(script);
+ public NashornJsEngine(String script, String functionName) {
+ String jsWrapperPrefix = String.format(JS_WRAPPER_PREFIX_TEMPLATE, functionName);
+ String jsWrapperSuffix = String.format(JS_WRAPPER_SUFFIX_TEMPLATE, functionName);
+ engine = compileScript(jsWrapperPrefix + script + jsWrapperSuffix);
}
private static CompiledScript compileScript(String script) {
@@ -58,15 +64,15 @@ public class NashornJsEngine {
public static Bindings bindMsg(TbMsg msg) {
try {
Bindings bindings = new SimpleBindings();
- bindings.put(METADATA, msg.getMetaData().getData());
-
if (ArrayUtils.isNotEmpty(msg.getData())) {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(msg.getData());
Map map = mapper.treeToValue(jsonNode, Map.class);
bindings.put(DATA, map);
+ } else {
+ bindings.put(DATA, Collections.emptyMap());
}
-
+ bindings.put(METADATA, msg.getMetaData().getData());
return bindings;
} catch (Throwable th) {
throw new IllegalArgumentException("Cannot bind js args", th);
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java
index 69ee9d7..4fc0f3e 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java
@@ -42,7 +42,7 @@ import static org.thingsboard.server.common.data.DataConstants.*;
nodeDescription = "Add Message Originator Attributes or Latest Telemetry into Message Metadata",
nodeDetails = "If Attributes enrichment configured, <b>CLIENT/SHARED/SERVER</b> attributes are added into Message metadata " +
"with specific prefix: <i>cs/shared/ss</i>. To access those attributes in other nodes this template can be used " +
- "<code>meta.cs.temperature</code> or <code>meta.shared.limit</code> " +
+ "<code>metadata.cs.temperature</code> or <code>metadata.shared.limit</code> " +
"If Latest Telemetry enrichment configured, latest telemetry added into metadata without prefix.")
public class TbGetAttributesNode implements TbNode {
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java
index cc6d6a1..c59a65e 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java
@@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
nodeDescription = "Add Originators Customer Attributes or Latest Telemetry into Message Metadata",
nodeDetails = "If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
"To access those attributes in other nodes this template can be used " +
- "<code>meta.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
+ "<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> {
@Override
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java
index 22c0b9f..4cd5cd5 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java
@@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
"If multiple Related Entities are found, only first Entity is used for attributes enrichment, other entities are discarded. " +
"If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
"To access those attributes in other nodes this template can be used " +
- "<code>meta.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
+ "<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> {
private TbGetRelatedAttrNodeConfiguration config;
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java
index b5f5e02..3165385 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java
@@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
nodeDescription = "Add Originators Tenant Attributes or Latest Telemetry into Message Metadata",
nodeDetails = "If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
"To access those attributes in other nodes this template can be used " +
- "<code>meta.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
+ "<code>metadata.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> {
@Override
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java
index 626790f..e47ea0f 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java
@@ -30,7 +30,7 @@ import javax.script.Bindings;
configClazz = TbTransformMsgNodeConfiguration.class,
nodeDescription = "Change Message payload and Metadata using JavaScript",
nodeDetails = "JavaScript function recieve 2 input parameters that can be changed inside.<br/> " +
- "<code>meta</code> - is a Message metadata.<br/>" +
+ "<code>metadata</code> - is a Message metadata.<br/>" +
"<code>msg</code> - is a Message payload.<br/>Any properties can be changed/removed/added in those objects.")
public class TbTransformMsgNode extends TbAbstractTransformNode {
@@ -40,7 +40,7 @@ public class TbTransformMsgNode extends TbAbstractTransformNode {
@Override
public void init(TbNodeConfiguration configuration, TbNodeState state) throws TbNodeException {
this.config = TbNodeUtils.convert(configuration, TbTransformMsgNodeConfiguration.class);
- this.jsEngine = new NashornJsEngine(config.getJsScript());
+ this.jsEngine = new NashornJsEngine(config.getJsScript(), "Transform");
setConfig(config);
}
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java
index 4f9e9eb..09d5ac4 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java
@@ -27,7 +27,7 @@ public class TbTransformMsgNodeConfiguration extends TbTransformNodeConfiguratio
public TbTransformMsgNodeConfiguration defaultConfiguration() {
TbTransformMsgNodeConfiguration configuration = new TbTransformMsgNodeConfiguration();
configuration.setStartNewChain(false);
- configuration.setJsScript("msg.passed = msg.passed * meta.temp; msg.bigObj.newProp = 'Ukraine' ");
+ configuration.setJsScript("return msg.passed = msg.passed * metadata.temp; msg.bigObj.newProp = 'Ukraine' ");
return configuration;
}
}
diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.css b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.css
new file mode 100644
index 0000000..a6103c1
--- /dev/null
+++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.css
@@ -0,0 +1,2 @@
+.tb-message-type-autocomplete .tb-not-found{display:block;line-height:1.5;height:48px}.tb-message-type-autocomplete .tb-not-found .tb-no-entries{line-height:48px}.tb-message-type-autocomplete li{height:auto!important;white-space:normal!important}
+/*# sourceMappingURL=rulenode-core-config.css.map*/
\ No newline at end of file
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 f254cf5..3fe859d 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,2 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var u=n[r]={exports:{},id:r,loaded:!1};return e[r].call(u.exports,u,u.exports,t),u.loaded=!0,u.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}([function(e,t,n){e.exports=n(3)},function(e,t){e.exports=' <section layout=column> <label translate class="tb-title no-padding">tb.rulenode.filter</label> <tb-js-func ng-model=configuration.jsScript function-name=Filter function-args="{{ [\'msg\'] }}" no-validate=true> </tb-js-func> </section> '},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function u(e){var t=function(t,n,r,u){var o=i.default;n.html(o),t.$watch("configuration",function(e,n){angular.equals(e,n)||u.$setViewValue(t.configuration)}),u.$render=function(){t.configuration=u.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}u.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=u;var o=n(1),i=r(o)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=n(2),o=r(u),i=n(5),a=r(i);t.default=angular.module("thingsboard.ruleChain.config",[]).directive("tbFilterNodeScriptConfig",o.default).config(a.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{filter:"Filter"}}};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 u(e,t){(0,i.default)(t);for(var n in t){var r=t[n];e.translations(n,r)}}u.$inject=["$translateProvider","locales"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=u;var o=n(4),i=r(o)}]);
+!function(e){function t(s){if(a[s])return a[s].exports;var n=a[s]={exports:{},id:s,loaded:!1};return e[s].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var a={};return t.m=e,t.c=a,t.p="/static/",t(0)}([function(e,t,a){e.exports=a(8)},function(e,t){},function(e,t){e.exports=' <section layout=column> <label translate class="tb-title no-padding" ng-class="{\'tb-required\': required}">tb.rulenode.message-types-filter</label> <md-chips id=message_type_chips ng-required=required readonly=readonly ng-model=messageTypes md-autocomplete-snap md-transform-chip=transformMessageTypeChip($chip) md-require-match=false> <md-autocomplete id=message_type md-no-cache=true md-selected-item=selectedMessageType md-search-text=messageTypeSearchText md-items="item in messageTypesSearch(messageTypeSearchText)" md-item-text=item.name md-min-length=0 placeholder="{{\'tb.rulenode.message-type\' | translate }}" md-menu-class=tb-message-type-autocomplete> <span md-highlight-text=messageTypeSearchText md-highlight-flags=^i>{{item}}</span> <md-not-found> <div class=tb-not-found> <div class=tb-no-entries ng-if="!messageTypeSearchText || !messageTypeSearchText.length"> <span translate>tb.rulenode.no-message-types-found</span> </div> <div ng-if="messageTypeSearchText && messageTypeSearchText.length"> <span translate translate-values=\'{ messageType: "{{messageTypeSearchText | truncate:true:6:'...'}}" }\'>tb.rulenode.no-message-type-matching</span> <span> <a translate ng-click="createMessageType($event, \'#message_type_chips\')">tb.rulenode.create-new-message-type</a> </span> </div> </div> </md-not-found> </md-autocomplete> <md-chip-template> <span>{{$chip.name}}</span> </md-chip-template> </md-chips> <div class=tb-error-messages ng-messages=ngModelCtrl.$error role=alert> <div translate ng-message=messageTypes class=tb-error-message>tb.rulenode.message-types-required</div> </div> </section>'},function(e,t){e.exports=" <section layout=column> <label translate class=\"tb-title no-padding\">tb.rulenode.filter</label> <tb-js-func ng-model=configuration.jsScript function-name=Filter function-args=\"{{ ['msg', 'metadata'] }}\" no-validate=true> </tb-js-func> </section> "},function(e,t){e.exports=" <section layout=column> <label translate class=\"tb-title no-padding\">tb.rulenode.switch</label> <tb-js-func ng-model=configuration.jsScript function-name=Switch function-args=\"{{ ['msg', 'metadata'] }}\" no-validate=true> </tb-js-func> </section> "},function(e,t,a){"use strict";function s(e){return e&&e.__esModule?e:{default:e}}function n(e,t,a){var s=function(s,n,r,l){function u(){if(l.$viewValue){for(var e=[],t=0;t<s.messageTypes.length;t++)e.push(s.messageTypes[t].value);l.$viewValue.messageTypes=e,o()}}function o(){if(s.required){var e=!(!l.$viewValue.messageTypes||!l.$viewValue.messageTypes.length);l.$setValidity("messageTypes",e)}else l.$setValidity("messageTypes",!0)}var c=i.default;n.html(c),s.selectedMessageType=null,s.messageTypeSearchText=null,s.ngModelCtrl=l;var d=[];for(var p in a.messageType){var m={name:a.messageType[p].name,value:a.messageType[p].value};d.push(m)}s.transformMessageTypeChip=function(e){var a,s=t("filter")(d,{name:e},!0);return a=s&&s.length?angular.copy(s[0]):{name:e,value:e}},s.messageTypesSearch=function(e){var a=e?t("filter")(d,{name:e}):d;return a.map(function(e){return e.name})},s.createMessageType=function(e,t){var a=angular.element(t,n)[0].firstElementChild,s=angular.element(a),r=s.scope().$mdChipsCtrl.getChipBuffer();e.preventDefault(),e.stopPropagation(),s.scope().$mdChipsCtrl.appendChip(r.trim()),s.scope().$mdChipsCtrl.resetChipBuffer()},l.$render=function(){var e=l.$viewValue,t=[];if(e&&e.messageTypes)for(var n=0;n<e.messageTypes.length;n++){var r=e.messageTypes[n];a.messageType[r]?t.push(angular.copy(a.messageType[r])):t.push({name:r,value:r})}s.messageTypes=t,s.$watch("messageTypes",function(e,t){angular.equals(e,t)||u()},!0)},e(n.contents())(s)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",readonly:"=ngReadonly"},link:s}}n.$inject=["$compile","$filter","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n,a(1);var r=a(2),i=s(r)},function(e,t,a){"use strict";function s(e){return e&&e.__esModule?e:{default:e}}function n(e){var t=function(t,a,s,n){var r=i.default;a.html(r),t.$watch("configuration",function(e,a){angular.equals(e,a)||n.$setViewValue(t.configuration)}),n.$render=function(){t.configuration=n.$viewValue},e(a.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}n.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n;var r=a(3),i=s(r)},function(e,t,a){"use strict";function s(e){return e&&e.__esModule?e:{default:e}}function n(e){var t=function(t,a,s,n){var r=i.default;a.html(r),t.$watch("configuration",function(e,a){angular.equals(e,a)||n.$setViewValue(t.configuration)}),n.$render=function(){t.configuration=n.$viewValue},e(a.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}n.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n;var r=a(4),i=s(r)},function(e,t,a){"use strict";function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=a(11),r=s(n),i=a(6),l=s(i),u=a(5),o=s(u),c=a(7),d=s(c),p=a(10),m=s(p);t.default=angular.module("thingsboard.ruleChain.config",[r.default]).directive("tbFilterNodeScriptConfig",l.default).directive("tbFilterNodeMessageTypeConfig",o.default).directive("tbFilterNodeSwitchConfig",d.default).config(m.default).name},function(e,t){"use strict";function a(e){var t={tb:{rulenode:{filter:"Filter",switch:"Switch","message-type":"Message type","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."}}};angular.merge(e.en_US,t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=a},function(e,t,a){"use strict";function s(e){return e&&e.__esModule?e:{default:e}}function n(e,t){(0,i.default)(t);for(var a in t){var s=t[a];e.translations(a,s)}}n.$inject=["$translateProvider","locales"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n;var r=a(9),i=s(r)},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"}}}).name}]);
//# sourceMappingURL=rulenode-core-config.js.map
\ No newline at end of file
diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java
index 96f7032..4c44886 100644
--- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java
+++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java
@@ -51,7 +51,7 @@ public class TbJsFilterNodeTest {
@Test
public void falseEvaluationDoNotSendMsg() throws TbNodeException {
- initWithScript("10 > 15;");
+ initWithScript("return 10 > 15;");
TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, new TbMsgMetaData(), "{}".getBytes());
mockJsExecutor();
@@ -64,7 +64,7 @@ public class TbJsFilterNodeTest {
@Test
public void notValidMsgDataThrowsException() throws TbNodeException {
- initWithScript("10 > 15;");
+ initWithScript("return 10 > 15;");
TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, new TbMsgMetaData(), new byte[4]);
when(ctx.getJsExecutor()).thenReturn(executor);
@@ -77,7 +77,7 @@ public class TbJsFilterNodeTest {
@Test
public void exceptionInJsThrowsException() throws TbNodeException {
- initWithScript("meta.temp.curr < 15;");
+ initWithScript("return metadata.temp.curr < 15;");
TbMsgMetaData metaData = new TbMsgMetaData();
TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, "{}".getBytes());
mockJsExecutor();
@@ -89,12 +89,12 @@ public class TbJsFilterNodeTest {
@Test(expected = IllegalArgumentException.class)
public void notValidScriptThrowsException() throws TbNodeException {
- initWithScript("10 > 15 asdq out");
+ initWithScript("return 10 > 15 asdq out");
}
@Test
public void metadataConditionCanBeFalse() throws TbNodeException {
- initWithScript("meta.humidity < 15;");
+ initWithScript("return metadata.humidity < 15;");
TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("temp", "10");
metaData.putValue("humidity", "99");
@@ -109,7 +109,7 @@ public class TbJsFilterNodeTest {
@Test
public void metadataConditionCanBeTrue() throws TbNodeException {
- initWithScript("meta.temp < 15;");
+ initWithScript("return metadata.temp < 15;");
TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("temp", "10");
metaData.putValue("humidity", "99");
@@ -123,7 +123,7 @@ public class TbJsFilterNodeTest {
@Test
public void msgJsonParsedAndBinded() throws TbNodeException {
- initWithScript("msg.passed < 15 && msg.name === 'Vit' && meta.temp == 10 && msg.bigObj.prop == 42;");
+ initWithScript("return msg.passed < 15 && msg.name === 'Vit' && metadata.temp == 10 && msg.bigObj.prop == 42;");
TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("temp", "10");
metaData.putValue("humidity", "99");
diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java
index e70d4e1..01227f4 100644
--- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java
+++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java
@@ -53,27 +53,16 @@ public class TbJsSwitchNodeTest {
private ListeningExecutor executor;
@Test
- public void routeToAllDoNotEvaluatesJs() throws TbNodeException {
- HashSet<String> relations = Sets.newHashSet("one", "two");
- initWithScript("test qwerty", relations, true);
- TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, new TbMsgMetaData(), "{}".getBytes());
-
- node.onMsg(ctx, msg);
- verify(ctx).tellNext(msg, relations);
- verifyNoMoreInteractions(ctx, executor);
- }
-
- @Test
public void multipleRoutesAreAllowed() throws TbNodeException {
- String jsCode = "function nextRelation(meta, msg) {\n" +
- " if(msg.passed == 5 && meta.temp == 10)\n" +
+ String jsCode = "function nextRelation(metadata, msg) {\n" +
+ " if(msg.passed == 5 && metadata.temp == 10)\n" +
" return ['three', 'one']\n" +
" else\n" +
" return 'two';\n" +
"};\n" +
"\n" +
- "nextRelation(meta, msg);";
- initWithScript(jsCode, Sets.newHashSet("one", "two", "three"), false);
+ "return nextRelation(metadata, msg);";
+ initWithScript(jsCode);
TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("temp", "10");
metaData.putValue("humidity", "99");
@@ -89,15 +78,15 @@ public class TbJsSwitchNodeTest {
@Test
public void allowedRelationPassed() throws TbNodeException {
- String jsCode = "function nextRelation(meta, msg) {\n" +
- " if(msg.passed == 5 && meta.temp == 10)\n" +
+ String jsCode = "function nextRelation(metadata, msg) {\n" +
+ " if(msg.passed == 5 && metadata.temp == 10)\n" +
" return 'one'\n" +
" else\n" +
" return 'two';\n" +
"};\n" +
"\n" +
- "nextRelation(meta, msg);";
- initWithScript(jsCode, Sets.newHashSet("one", "two"), false);
+ "return nextRelation(metadata, msg);";
+ initWithScript(jsCode);
TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("temp", "10");
metaData.putValue("humidity", "99");
@@ -111,32 +100,9 @@ public class TbJsSwitchNodeTest {
verify(ctx).tellNext(msg, Sets.newHashSet("one"));
}
- @Test
- public void unknownRelationThrowsException() throws TbNodeException {
- String jsCode = "function nextRelation(meta, msg) {\n" +
- " return ['one','nine'];" +
- "};\n" +
- "\n" +
- "nextRelation(meta, msg);";
- initWithScript(jsCode, Sets.newHashSet("one", "two"), false);
- TbMsgMetaData metaData = new TbMsgMetaData();
- metaData.putValue("temp", "10");
- metaData.putValue("humidity", "99");
- String rawJson = "{\"name\": \"Vit\", \"passed\": 5}";
-
- TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson.getBytes());
- mockJsExecutor();
-
- node.onMsg(ctx, msg);
- verify(ctx).getJsExecutor();
- verifyError(msg, "Unsupported relation for switch [nine, one]", IllegalStateException.class);
- }
-
- private void initWithScript(String script, Set<String> relations, boolean routeToAll) throws TbNodeException {
+ private void initWithScript(String script) throws TbNodeException {
TbJsSwitchNodeConfiguration config = new TbJsSwitchNodeConfiguration();
config.setJsScript(script);
- config.setAllowedRelations(relations);
- config.setRouteToAllWithNoCheck(routeToAll);
ObjectMapper mapper = new ObjectMapper();
TbNodeConfiguration nodeConfiguration = new TbNodeConfiguration(mapper.valueToTree(config));
diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java
index d69bad8..c6b3441 100644
--- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java
+++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java
@@ -51,7 +51,7 @@ public class TbTransformMsgNodeTest {
@Test
public void metadataCanBeUpdated() throws TbNodeException {
- initWithScript("meta.temp = meta.temp * 10;");
+ initWithScript("return metadata.temp = metadata.temp * 10;");
TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("temp", "7");
metaData.putValue("humidity", "99");
@@ -70,7 +70,7 @@ public class TbTransformMsgNodeTest {
@Test
public void metadataCanBeAdded() throws TbNodeException {
- initWithScript("meta.newAttr = meta.humidity - msg.passed;");
+ initWithScript("return metadata.newAttr = metadata.humidity - msg.passed;");
TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("temp", "7");
metaData.putValue("humidity", "99");
@@ -89,7 +89,7 @@ public class TbTransformMsgNodeTest {
@Test
public void payloadCanBeUpdated() throws TbNodeException {
- initWithScript("msg.passed = msg.passed * meta.temp; msg.bigObj.newProp = 'Ukraine' ");
+ initWithScript("return msg.passed = msg.passed * metadata.temp; msg.bigObj.newProp = 'Ukraine' ");
TbMsgMetaData metaData = new TbMsgMetaData();
metaData.putValue("temp", "7");
metaData.putValue("humidity", "99");
ui/server.js 1(+0 -1)
diff --git a/ui/server.js b/ui/server.js
index 0513600..65a2bc7 100644
--- a/ui/server.js
+++ b/ui/server.js
@@ -32,7 +32,6 @@ const forwardPort = 8080;
const ruleNodeUiforwardHost = 'localhost';
const ruleNodeUiforwardPort = 8080;
-//const ruleNodeUiforwardPort = 5000;
const app = express();
const server = http.createServer(app);
diff --git a/ui/src/app/components/json-object-edit.directive.js b/ui/src/app/components/json-object-edit.directive.js
index db0aa60..215b7b9 100644
--- a/ui/src/app/components/json-object-edit.directive.js
+++ b/ui/src/app/components/json-object-edit.directive.js
@@ -84,17 +84,32 @@ function JsonObjectEdit($compile, $templateCache, $document, toast, utils) {
scope.$watch('contentBody', function (newVal, prevVal) {
if (!angular.equals(newVal, prevVal)) {
var object = scope.validate();
- ngModelCtrl.$setViewValue(object);
+ if (scope.objectValid) {
+ if (object == null) {
+ scope.object = null;
+ } else {
+ if (scope.object == null) {
+ scope.object = {};
+ }
+ Object.keys(scope.object).forEach(function (key) {
+ delete scope.object[key];
+ });
+ Object.keys(object).forEach(function (key) {
+ scope.object[key] = object[key];
+ });
+ }
+ ngModelCtrl.$setViewValue(scope.object);
+ }
scope.updateValidity();
}
});
ngModelCtrl.$render = function () {
- var object = ngModelCtrl.$viewValue;
+ scope.object = ngModelCtrl.$viewValue;
var content = '';
try {
- if (object) {
- content = angular.toJson(object, true);
+ if (scope.object) {
+ content = angular.toJson(scope.object, true);
}
} catch (e) {
//
ui/src/app/locale/locale.constant.js 1(+1 -0)
diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js
index b511b56..a70ca14 100644
--- a/ui/src/app/locale/locale.constant.js
+++ b/ui/src/app/locale/locale.constant.js
@@ -1171,6 +1171,7 @@ export default angular.module('thingsboard.locale', [])
"debug-mode": "Debug mode"
},
"rulenode": {
+ "details": "Details",
"add": "Add rule node",
"name": "Name",
"name-required": "Name is required.",
diff --git a/ui/src/app/rulechain/rulechain.controller.js b/ui/src/app/rulechain/rulechain.controller.js
index dd48bb0..fbdda22 100644
--- a/ui/src/app/rulechain/rulechain.controller.js
+++ b/ui/src/app/rulechain/rulechain.controller.js
@@ -256,6 +256,9 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
vm.isEditingRuleNodeLink = true;
vm.editingRuleNodeLinkIndex = vm.ruleChainModel.edges.indexOf(edge);
vm.editingRuleNodeLink = angular.copy(edge);
+ $mdUtil.nextTick(() => {
+ vm.ruleNodeLinkForm.$setPristine();
+ });
}
},
nodeCallbacks: {
@@ -266,6 +269,9 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
vm.isEditingRuleNode = true;
vm.editingRuleNodeIndex = vm.ruleChainModel.nodes.indexOf(node);
vm.editingRuleNode = angular.copy(node);
+ $mdUtil.nextTick(() => {
+ vm.ruleNodeForm.$setPristine();
+ });
}
}
},
ui/src/app/rulechain/rulechain.tpl.html 27(+16 -11)
diff --git a/ui/src/app/rulechain/rulechain.tpl.html b/ui/src/app/rulechain/rulechain.tpl.html
index d23f920..3083f83 100644
--- a/ui/src/app/rulechain/rulechain.tpl.html
+++ b/ui/src/app/rulechain/rulechain.tpl.html
@@ -65,7 +65,8 @@
</div>
<tb-details-sidenav class="tb-rulenode-details-sidenav"
header-title="{{vm.editingRuleNode.name}}"
- header-subtitle="{{'rulenode.rulenode-details' | translate}}"
+ header-subtitle="{{(vm.types.ruleNodeType[vm.editingRuleNode.component.type].name | translate)
+ + ' - ' + vm.editingRuleNode.component.name}}"
is-read-only="false"
is-open="vm.isEditingRuleNode"
is-always-edit="true"
@@ -76,16 +77,20 @@
<details-buttons tb-help="vm.helpLinkIdForRuleNodeType()" help-container-id="help-container">
<div id="help-container"></div>
</details-buttons>
- <form name="vm.ruleNodeForm" ng-if="vm.isEditingRuleNode">
- <tb-rule-node
- rule-node="vm.editingRuleNode"
- rule-chain-id="vm.ruleChain.id.id"
- is-edit="true"
- is-read-only="false"
- on-delete-rule-node="vm.deleteRuleNode(event, vm.editingRuleNode)"
- the-form="vm.ruleNodeForm">
- </tb-rule-node>
- </form>
+ <md-tabs id="ruleNodeTabs" md-border-bottom flex class="tb-absolute-fill">
+ <md-tab label="{{ 'rulenode.details' | translate }}">
+ <form name="vm.ruleNodeForm" ng-if="vm.isEditingRuleNode">
+ <tb-rule-node
+ rule-node="vm.editingRuleNode"
+ rule-chain-id="vm.ruleChain.id.id"
+ is-edit="true"
+ is-read-only="false"
+ on-delete-rule-node="vm.deleteRuleNode(event, vm.editingRuleNode)"
+ the-form="vm.ruleNodeForm">
+ </tb-rule-node>
+ </form>
+ </md-tab>
+ </md-tabs>
</tb-details-sidenav>
<tb-details-sidenav class="tb-rulenode-link-details-sidenav"
header-title="{{vm.editingRuleNodeLink.label}}"
diff --git a/ui/src/app/rulechain/rulenode-config.directive.js b/ui/src/app/rulechain/rulenode-config.directive.js
index 4b75c79..9bb8c48 100644
--- a/ui/src/app/rulechain/rulenode-config.directive.js
+++ b/ui/src/app/rulechain/rulenode-config.directive.js
@@ -38,10 +38,15 @@ export default function RuleNodeConfigDirective($compile, $templateCache, $injec
};
scope.useDefinedDirective = function() {
- return scope.nodeDefinition.configDirective && !scope.definedDirectiveError;
+ return scope.nodeDefinition &&
+ scope.nodeDefinition.configDirective && !scope.definedDirectiveError;
};
- validateDefinedDirective();
+ scope.$watch('nodeDefinition', () => {
+ if (scope.nodeDefinition) {
+ validateDefinedDirective();
+ }
+ });
function validateDefinedDirective() {
if (scope.nodeDefinition.uiResourceLoadError && scope.nodeDefinition.uiResourceLoadError.length) {
diff --git a/ui/src/app/rulechain/rulenode-defined-config.directive.js b/ui/src/app/rulechain/rulenode-defined-config.directive.js
index 5ec2620..5100fbb 100644
--- a/ui/src/app/rulechain/rulenode-defined-config.directive.js
+++ b/ui/src/app/rulechain/rulenode-defined-config.directive.js
@@ -36,10 +36,14 @@ export default function RuleNodeDefinedConfigDirective($compile) {
};
function loadTemplate() {
+ if (scope.ruleNodeConfigScope) {
+ scope.ruleNodeConfigScope.$destroy();
+ }
var directive = snake_case(attrs.ruleNodeDirective, '-');
var template = `<${directive} ng-model="configuration" ng-required="required" ng-readonly="readonly"></${directive}>`;
element.html(template);
- $compile(element.contents())(scope);
+ scope.ruleNodeConfigScope = scope.$new();
+ $compile(element.contents())(scope.ruleNodeConfigScope);
}
function snake_case(name, separator) {
ui/src/app/rulechain/rulenode-fieldset.tpl.html 35(+14 -21)
diff --git a/ui/src/app/rulechain/rulenode-fieldset.tpl.html b/ui/src/app/rulechain/rulenode-fieldset.tpl.html
index ad109ef..7b0fae5 100644
--- a/ui/src/app/rulechain/rulenode-fieldset.tpl.html
+++ b/ui/src/app/rulechain/rulenode-fieldset.tpl.html
@@ -21,33 +21,26 @@
<md-content class="md-padding tb-rulenode" layout="column">
<fieldset ng-disabled="$root.loading || !isEdit || isReadOnly">
- <md-input-container class="md-block">
- <label translate>rulenode.type</label>
- <input readonly name="type" ng-model="ruleNode.component.name">
- </md-input-container>
<section ng-if="ruleNode.component.type != types.ruleNodeType.RULE_CHAIN.value">
- <md-input-container class="md-block">
- <label translate>rulenode.name</label>
- <input required name="name" ng-model="ruleNode.name">
- <div ng-messages="theForm.name.$error">
- <div translate ng-message="required">rulenode.name-required</div>
- </div>
- </md-input-container>
- <md-input-container class="md-block">
- <md-checkbox ng-disabled="$root.loading || !isEdit" aria-label="{{ 'rulenode.debug-mode' | translate }}"
- ng-model="ruleNode.debugMode">{{ 'rulenode.debug-mode' | translate }}
- </md-checkbox>
- </md-input-container>
+ <section layout="column" layout-gt-sm="row">
+ <md-input-container flex class="md-block">
+ <label translate>rulenode.name</label>
+ <input required name="name" ng-model="ruleNode.name">
+ <div ng-messages="theForm.name.$error">
+ <div translate ng-message="required">rulenode.name-required</div>
+ </div>
+ </md-input-container>
+ <md-input-container class="md-block">
+ <md-checkbox ng-disabled="$root.loading || !isEdit" aria-label="{{ 'rulenode.debug-mode' | translate }}"
+ ng-model="ruleNode.debugMode">{{ 'rulenode.debug-mode' | translate }}
+ </md-checkbox>
+ </md-input-container>
+ </section>
<tb-rule-node-config ng-model="ruleNode.configuration"
ng-required="true"
node-definition="ruleNode.component.configurationDescriptor.nodeDefinition"
ng-readonly="$root.loading || !isEdit || isReadOnly">
</tb-rule-node-config>
- <!--tb-json-object-edit class="tb-rule-node-configuration-json" ng-model="ruleNode.configuration"
- label="{{ 'rulenode.configuration' | translate }}"
- ng-required="true"
- fill-height="true">
- </tb-json-object-edit-->
<md-input-container class="md-block">
<label translate>rulenode.description</label>
<textarea ng-model="ruleNode.additionalInfo.description" rows="2"></textarea>