Commit 344f6045a64dd2f3ff9aaeade9629868fd63754d
1 parent
a5c59e5c
Use ComponentDescriptors in RuleChain UI
Showing
14 changed files
with
161 additions
and
116 deletions
@@ -71,6 +71,7 @@ import javax.servlet.http.HttpServletRequest; | @@ -71,6 +71,7 @@ import javax.servlet.http.HttpServletRequest; | ||
71 | import javax.servlet.http.HttpServletResponse; | 71 | import javax.servlet.http.HttpServletResponse; |
72 | import java.util.List; | 72 | import java.util.List; |
73 | import java.util.Optional; | 73 | import java.util.Optional; |
74 | +import java.util.Set; | ||
74 | import java.util.UUID; | 75 | import java.util.UUID; |
75 | 76 | ||
76 | import static org.thingsboard.server.dao.service.Validator.validateId; | 77 | import static org.thingsboard.server.dao.service.Validator.validateId; |
@@ -480,6 +481,15 @@ public abstract class BaseController { | @@ -480,6 +481,15 @@ public abstract class BaseController { | ||
480 | } | 481 | } |
481 | } | 482 | } |
482 | 483 | ||
484 | + List<ComponentDescriptor> checkComponentDescriptorsByTypes(Set<ComponentType> types) throws ThingsboardException { | ||
485 | + try { | ||
486 | + log.debug("[{}] Lookup component descriptors", types); | ||
487 | + return componentDescriptorService.getComponents(types); | ||
488 | + } catch (Exception e) { | ||
489 | + throw handleException(e, false); | ||
490 | + } | ||
491 | + } | ||
492 | + | ||
483 | List<ComponentDescriptor> checkPluginActionsByPluginClazz(String pluginClazz) throws ThingsboardException { | 493 | List<ComponentDescriptor> checkPluginActionsByPluginClazz(String pluginClazz) throws ThingsboardException { |
484 | try { | 494 | try { |
485 | checkComponentDescriptorByClazz(pluginClazz); | 495 | checkComponentDescriptorByClazz(pluginClazz); |
@@ -21,7 +21,9 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor; | @@ -21,7 +21,9 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor; | ||
21 | import org.thingsboard.server.common.data.plugin.ComponentType; | 21 | import org.thingsboard.server.common.data.plugin.ComponentType; |
22 | import org.thingsboard.server.exception.ThingsboardException; | 22 | import org.thingsboard.server.exception.ThingsboardException; |
23 | 23 | ||
24 | +import java.util.HashSet; | ||
24 | import java.util.List; | 25 | import java.util.List; |
26 | +import java.util.Set; | ||
25 | 27 | ||
26 | @RestController | 28 | @RestController |
27 | @RequestMapping("/api") | 29 | @RequestMapping("/api") |
@@ -52,6 +54,22 @@ public class ComponentDescriptorController extends BaseController { | @@ -52,6 +54,22 @@ public class ComponentDescriptorController extends BaseController { | ||
52 | } | 54 | } |
53 | 55 | ||
54 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") | 56 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") |
57 | + @RequestMapping(value = "/components", params = {"componentTypes"}, method = RequestMethod.GET) | ||
58 | + @ResponseBody | ||
59 | + public List<ComponentDescriptor> getComponentDescriptorsByTypes(@RequestParam("componentTypes") String[] strComponentTypes) throws ThingsboardException { | ||
60 | + checkArrayParameter("componentTypes", strComponentTypes); | ||
61 | + try { | ||
62 | + Set<ComponentType> componentTypes = new HashSet<>(); | ||
63 | + for (String strComponentType : strComponentTypes) { | ||
64 | + componentTypes.add(ComponentType.valueOf(strComponentType)); | ||
65 | + } | ||
66 | + return checkComponentDescriptorsByTypes(componentTypes); | ||
67 | + } catch (Exception e) { | ||
68 | + throw handleException(e); | ||
69 | + } | ||
70 | + } | ||
71 | + | ||
72 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") | ||
55 | @RequestMapping(value = "/components/actions/{pluginClazz:.+}", method = RequestMethod.GET) | 73 | @RequestMapping(value = "/components/actions/{pluginClazz:.+}", method = RequestMethod.GET) |
56 | @ResponseBody | 74 | @ResponseBody |
57 | public List<ComponentDescriptor> getPluginActionsByPluginClazz(@PathVariable("pluginClazz") String pluginClazz) throws ThingsboardException { | 75 | public List<ComponentDescriptor> getPluginActionsByPluginClazz(@PathVariable("pluginClazz") String pluginClazz) throws ThingsboardException { |
@@ -204,6 +204,15 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe | @@ -204,6 +204,15 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe | ||
204 | } | 204 | } |
205 | 205 | ||
206 | @Override | 206 | @Override |
207 | + public List<ComponentDescriptor> getComponents(Set<ComponentType> types) { | ||
208 | + List<ComponentDescriptor> result = new ArrayList<>(); | ||
209 | + for (ComponentType type : types) { | ||
210 | + result.addAll(componentsMap.get(type)); | ||
211 | + } | ||
212 | + return Collections.unmodifiableList(result); | ||
213 | + } | ||
214 | + | ||
215 | + @Override | ||
207 | public Optional<ComponentDescriptor> getComponent(String clazz) { | 216 | public Optional<ComponentDescriptor> getComponent(String clazz) { |
208 | return Optional.ofNullable(components.get(clazz)); | 217 | return Optional.ofNullable(components.get(clazz)); |
209 | } | 218 | } |
@@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; | @@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; | ||
20 | 20 | ||
21 | import java.util.List; | 21 | import java.util.List; |
22 | import java.util.Optional; | 22 | import java.util.Optional; |
23 | +import java.util.Set; | ||
23 | 24 | ||
24 | /** | 25 | /** |
25 | * @author Andrew Shvayka | 26 | * @author Andrew Shvayka |
@@ -30,6 +31,8 @@ public interface ComponentDiscoveryService { | @@ -30,6 +31,8 @@ public interface ComponentDiscoveryService { | ||
30 | 31 | ||
31 | List<ComponentDescriptor> getComponents(ComponentType type); | 32 | List<ComponentDescriptor> getComponents(ComponentType type); |
32 | 33 | ||
34 | + List<ComponentDescriptor> getComponents(Set<ComponentType> types); | ||
35 | + | ||
33 | Optional<ComponentDescriptor> getComponent(String clazz); | 36 | Optional<ComponentDescriptor> getComponent(String clazz); |
34 | 37 | ||
35 | List<ComponentDescriptor> getPluginActions(String pluginClazz); | 38 | List<ComponentDescriptor> getPluginActions(String pluginClazz); |
@@ -26,7 +26,8 @@ function ComponentDescriptorService($http, $q) { | @@ -26,7 +26,8 @@ function ComponentDescriptorService($http, $q) { | ||
26 | var service = { | 26 | var service = { |
27 | getComponentDescriptorsByType: getComponentDescriptorsByType, | 27 | getComponentDescriptorsByType: getComponentDescriptorsByType, |
28 | getComponentDescriptorByClazz: getComponentDescriptorByClazz, | 28 | getComponentDescriptorByClazz: getComponentDescriptorByClazz, |
29 | - getPluginActionsByPluginClazz: getPluginActionsByPluginClazz | 29 | + getPluginActionsByPluginClazz: getPluginActionsByPluginClazz, |
30 | + getComponentDescriptorsByTypes: getComponentDescriptorsByTypes | ||
30 | } | 31 | } |
31 | 32 | ||
32 | return service; | 33 | return service; |
@@ -52,6 +53,41 @@ function ComponentDescriptorService($http, $q) { | @@ -52,6 +53,41 @@ function ComponentDescriptorService($http, $q) { | ||
52 | return deferred.promise; | 53 | return deferred.promise; |
53 | } | 54 | } |
54 | 55 | ||
56 | + function getComponentDescriptorsByTypes(componentTypes) { | ||
57 | + var deferred = $q.defer(); | ||
58 | + var result = []; | ||
59 | + for (var i=componentTypes.length-1;i>=0;i--) { | ||
60 | + var componentType = componentTypes[i]; | ||
61 | + if (componentsByType[componentType]) { | ||
62 | + result = result.concat(componentsByType[componentType]); | ||
63 | + componentTypes.splice(i, 1); | ||
64 | + } | ||
65 | + } | ||
66 | + if (!componentTypes.length) { | ||
67 | + deferred.resolve(result); | ||
68 | + } else { | ||
69 | + var url = '/api/components?componentTypes=' + componentTypes.join(','); | ||
70 | + $http.get(url, null).then(function success(response) { | ||
71 | + var components = response.data; | ||
72 | + for (var i = 0; i < components.length; i++) { | ||
73 | + var component = components[i]; | ||
74 | + var componentsList = componentsByType[component.type]; | ||
75 | + if (!componentsList) { | ||
76 | + componentsList = []; | ||
77 | + componentsByType[component.type] = componentsList; | ||
78 | + } | ||
79 | + componentsList.push(component); | ||
80 | + componentsByClazz[component.clazz] = component; | ||
81 | + } | ||
82 | + result = result.concat(components); | ||
83 | + deferred.resolve(components); | ||
84 | + }, function fail() { | ||
85 | + deferred.reject(); | ||
86 | + }); | ||
87 | + } | ||
88 | + return deferred.promise; | ||
89 | + } | ||
90 | + | ||
55 | function getComponentDescriptorByClazz(componentDescriptorClazz) { | 91 | function getComponentDescriptorByClazz(componentDescriptorClazz) { |
56 | var deferred = $q.defer(); | 92 | var deferred = $q.defer(); |
57 | if (componentsByClazz[componentDescriptorClazz]) { | 93 | if (componentsByClazz[componentDescriptorClazz]) { |
@@ -17,9 +17,9 @@ export default angular.module('thingsboard.api.ruleChain', []) | @@ -17,9 +17,9 @@ export default angular.module('thingsboard.api.ruleChain', []) | ||
17 | .factory('ruleChainService', RuleChainService).name; | 17 | .factory('ruleChainService', RuleChainService).name; |
18 | 18 | ||
19 | /*@ngInject*/ | 19 | /*@ngInject*/ |
20 | -function RuleChainService($http, $q, $filter, types) { | 20 | +function RuleChainService($http, $q, $filter, types, componentDescriptorService) { |
21 | 21 | ||
22 | - var ruleNodeTypes = null; | 22 | + var ruleNodeComponents = null; |
23 | 23 | ||
24 | var service = { | 24 | var service = { |
25 | getSystemRuleChains: getSystemRuleChains, | 25 | getSystemRuleChains: getSystemRuleChains, |
@@ -30,8 +30,8 @@ function RuleChainService($http, $q, $filter, types) { | @@ -30,8 +30,8 @@ function RuleChainService($http, $q, $filter, types) { | ||
30 | deleteRuleChain: deleteRuleChain, | 30 | deleteRuleChain: deleteRuleChain, |
31 | getRuleChainMetaData: getRuleChainMetaData, | 31 | getRuleChainMetaData: getRuleChainMetaData, |
32 | saveRuleChainMetaData: saveRuleChainMetaData, | 32 | saveRuleChainMetaData: saveRuleChainMetaData, |
33 | - getRuleNodeTypes: getRuleNodeTypes, | ||
34 | - getRuleNodeComponentType: getRuleNodeComponentType, | 33 | + getRuleNodeComponents: getRuleNodeComponents, |
34 | + getRuleNodeComponentByClazz: getRuleNodeComponentByClazz, | ||
35 | getRuleNodeSupportedLinks: getRuleNodeSupportedLinks, | 35 | getRuleNodeSupportedLinks: getRuleNodeSupportedLinks, |
36 | resolveTargetRuleChains: resolveTargetRuleChains | 36 | resolveTargetRuleChains: resolveTargetRuleChains |
37 | }; | 37 | }; |
@@ -165,21 +165,18 @@ function RuleChainService($http, $q, $filter, types) { | @@ -165,21 +165,18 @@ function RuleChainService($http, $q, $filter, types) { | ||
165 | return deferred.promise; | 165 | return deferred.promise; |
166 | } | 166 | } |
167 | 167 | ||
168 | - function getRuleNodeTypes() { | 168 | + function getRuleNodeComponents() { |
169 | var deferred = $q.defer(); | 169 | var deferred = $q.defer(); |
170 | - if (ruleNodeTypes) { | ||
171 | - deferred.resolve(ruleNodeTypes); | 170 | + if (ruleNodeComponents) { |
171 | + deferred.resolve(ruleNodeComponents); | ||
172 | } else { | 172 | } else { |
173 | - loadRuleNodeTypes().then( | ||
174 | - (nodeTypes) => { | ||
175 | - ruleNodeTypes = nodeTypes; | ||
176 | - ruleNodeTypes.push( | ||
177 | - { | ||
178 | - nodeType: types.ruleNodeType.RULE_CHAIN.value, | ||
179 | - type: 'Rule chain' | ||
180 | - } | 173 | + loadRuleNodeComponents().then( |
174 | + (components) => { | ||
175 | + ruleNodeComponents = components; | ||
176 | + ruleNodeComponents.push( | ||
177 | + types.ruleChainNodeComponent | ||
181 | ); | 178 | ); |
182 | - deferred.resolve(ruleNodeTypes); | 179 | + deferred.resolve(ruleNodeComponents); |
183 | }, | 180 | }, |
184 | () => { | 181 | () => { |
185 | deferred.reject(); | 182 | deferred.reject(); |
@@ -189,10 +186,10 @@ function RuleChainService($http, $q, $filter, types) { | @@ -189,10 +186,10 @@ function RuleChainService($http, $q, $filter, types) { | ||
189 | return deferred.promise; | 186 | return deferred.promise; |
190 | } | 187 | } |
191 | 188 | ||
192 | - function getRuleNodeComponentType(type) { | ||
193 | - var res = $filter('filter')(ruleNodeTypes, {type: type}, true); | 189 | + function getRuleNodeComponentByClazz(clazz) { |
190 | + var res = $filter('filter')(ruleNodeComponents, {clazz: clazz}, true); | ||
194 | if (res && res.length) { | 191 | if (res && res.length) { |
195 | - return res[0].nodeType; | 192 | + return res[0]; |
196 | } | 193 | } |
197 | return null; | 194 | return null; |
198 | } | 195 | } |
@@ -222,61 +219,8 @@ function RuleChainService($http, $q, $filter, types) { | @@ -222,61 +219,8 @@ function RuleChainService($http, $q, $filter, types) { | ||
222 | return deferred.promise; | 219 | return deferred.promise; |
223 | } | 220 | } |
224 | 221 | ||
225 | - function loadRuleNodeTypes() { | ||
226 | - var deferred = $q.defer(); | ||
227 | - deferred.resolve( | ||
228 | - [ | ||
229 | - { | ||
230 | - nodeType: types.ruleNodeType.FILTER.value, | ||
231 | - type: 'Filter' | ||
232 | - }, | ||
233 | - { | ||
234 | - nodeType: types.ruleNodeType.FILTER.value, | ||
235 | - type: 'Switch' | ||
236 | - }, | ||
237 | - { | ||
238 | - nodeType: types.ruleNodeType.ENRICHMENT.value, | ||
239 | - type: 'Self' | ||
240 | - }, | ||
241 | - { | ||
242 | - nodeType: types.ruleNodeType.ENRICHMENT.value, | ||
243 | - type: 'Tenant/Customer' | ||
244 | - }, | ||
245 | - { | ||
246 | - nodeType: types.ruleNodeType.ENRICHMENT.value, | ||
247 | - type: 'Related Entity' | ||
248 | - }, | ||
249 | - { | ||
250 | - nodeType: types.ruleNodeType.ENRICHMENT.value, | ||
251 | - type: 'Last Telemetry' | ||
252 | - }, | ||
253 | - { | ||
254 | - nodeType: types.ruleNodeType.TRANSFORMATION.value, | ||
255 | - type: 'Modify' | ||
256 | - }, | ||
257 | - { | ||
258 | - nodeType: types.ruleNodeType.TRANSFORMATION.value, | ||
259 | - type: 'New/Update' | ||
260 | - }, | ||
261 | - { | ||
262 | - nodeType: types.ruleNodeType.ACTION.value, | ||
263 | - type: 'Telemetry' | ||
264 | - }, | ||
265 | - { | ||
266 | - nodeType: types.ruleNodeType.ACTION.value, | ||
267 | - type: 'RPC call' | ||
268 | - }, | ||
269 | - { | ||
270 | - nodeType: types.ruleNodeType.ACTION.value, | ||
271 | - type: 'Send email' | ||
272 | - }, | ||
273 | - { | ||
274 | - nodeType: types.ruleNodeType.ACTION.value, | ||
275 | - type: 'Alarm' | ||
276 | - } | ||
277 | - ] | ||
278 | - ); | ||
279 | - return deferred.promise; | 222 | + function loadRuleNodeComponents() { |
223 | + return componentDescriptorService.getComponentDescriptorsByTypes(types.ruleNodeTypeComponentTypes); | ||
280 | } | 224 | } |
281 | 225 | ||
282 | 226 |
@@ -457,6 +457,17 @@ export default angular.module('thingsboard.types', []) | @@ -457,6 +457,17 @@ export default angular.module('thingsboard.types', []) | ||
457 | clientSide: false | 457 | clientSide: false |
458 | } | 458 | } |
459 | }, | 459 | }, |
460 | + ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION"], | ||
461 | + ruleChainNodeComponent: { | ||
462 | + type: 'RULE_CHAIN', | ||
463 | + name: 'Rule chain', | ||
464 | + clazz: 'tb.internal.RuleChain' | ||
465 | + }, | ||
466 | + inputNodeComponent: { | ||
467 | + type: 'INPUT', | ||
468 | + name: 'Input', | ||
469 | + clazz: 'tb.internal.Input' | ||
470 | + }, | ||
460 | ruleNodeType: { | 471 | ruleNodeType: { |
461 | FILTER: { | 472 | FILTER: { |
462 | value: "FILTER", | 473 | value: "FILTER", |
@@ -1167,7 +1167,8 @@ export default angular.module('thingsboard.locale', []) | @@ -1167,7 +1167,8 @@ export default angular.module('thingsboard.locale', []) | ||
1167 | "select-rulechain": "Select rule chain", | 1167 | "select-rulechain": "Select rule chain", |
1168 | "no-rulechains-matching": "No rule chains matching '{{entity}}' were found.", | 1168 | "no-rulechains-matching": "No rule chains matching '{{entity}}' were found.", |
1169 | "rulechain-required": "Rule chain is required", | 1169 | "rulechain-required": "Rule chain is required", |
1170 | - "management": "Rules management" | 1170 | + "management": "Rules management", |
1171 | + "debug-mode": "Debug mode" | ||
1171 | }, | 1172 | }, |
1172 | "rulenode": { | 1173 | "rulenode": { |
1173 | "add": "Add rule node", | 1174 | "add": "Add rule node", |
@@ -1177,6 +1178,7 @@ export default angular.module('thingsboard.locale', []) | @@ -1177,6 +1178,7 @@ export default angular.module('thingsboard.locale', []) | ||
1177 | "description": "Description", | 1178 | "description": "Description", |
1178 | "delete": "Delete rule node", | 1179 | "delete": "Delete rule node", |
1179 | "rulenode-details": "Rule node details", | 1180 | "rulenode-details": "Rule node details", |
1181 | + "debug-mode": "Debug mode", | ||
1180 | "link-details": "Rule node link details", | 1182 | "link-details": "Rule node link details", |
1181 | "add-link": "Add link", | 1183 | "add-link": "Add link", |
1182 | "link-label": "Link label", | 1184 | "link-label": "Link label", |
@@ -42,6 +42,11 @@ | @@ -42,6 +42,11 @@ | ||
42 | </div> | 42 | </div> |
43 | </md-input-container> | 43 | </md-input-container> |
44 | <md-input-container class="md-block"> | 44 | <md-input-container class="md-block"> |
45 | + <md-checkbox ng-disabled="$root.loading || !isEdit" aria-label="{{ 'rulechain.debug-mode' | translate }}" | ||
46 | + ng-model="ruleChain.debugMode">{{ 'rulechain.debug-mode' | translate }} | ||
47 | + </md-checkbox> | ||
48 | + </md-input-container> | ||
49 | + <md-input-container class="md-block"> | ||
45 | <label translate>rulechain.description</label> | 50 | <label translate>rulechain.description</label> |
46 | <textarea ng-model="ruleChain.additionalInfo.description" rows="2"></textarea> | 51 | <textarea ng-model="ruleChain.additionalInfo.description" rows="2"></textarea> |
47 | </md-input-container> | 52 | </md-input-container> |
@@ -54,6 +54,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -54,6 +54,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
54 | }; | 54 | }; |
55 | 55 | ||
56 | vm.ruleNodeTypesModel = {}; | 56 | vm.ruleNodeTypesModel = {}; |
57 | + vm.ruleChainLibraryLoaded = false; | ||
57 | for (var type in types.ruleNodeType) { | 58 | for (var type in types.ruleNodeType) { |
58 | if (!types.ruleNodeType[type].special) { | 59 | if (!types.ruleNodeType[type].special) { |
59 | vm.ruleNodeTypesModel[type] = { | 60 | vm.ruleNodeTypesModel[type] = { |
@@ -141,8 +142,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -141,8 +142,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
141 | vm.editCallbacks = { | 142 | vm.editCallbacks = { |
142 | edgeDoubleClick: function (event, edge) { | 143 | edgeDoubleClick: function (event, edge) { |
143 | var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); | 144 | var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); |
144 | - if (sourceNode.nodeType != types.ruleNodeType.INPUT.value) { | ||
145 | - ruleChainService.getRuleNodeSupportedLinks(sourceNode.type).then( | 145 | + if (sourceNode.component.type != types.ruleNodeType.INPUT.value) { |
146 | + ruleChainService.getRuleNodeSupportedLinks(sourceNode.component.clazz).then( | ||
146 | (labels) => { | 147 | (labels) => { |
147 | vm.isEditingRuleNode = false; | 148 | vm.isEditingRuleNode = false; |
148 | vm.editingRuleNode = null; | 149 | vm.editingRuleNode = null; |
@@ -156,7 +157,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -156,7 +157,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
156 | }, | 157 | }, |
157 | nodeCallbacks: { | 158 | nodeCallbacks: { |
158 | 'doubleClick': function (event, node) { | 159 | 'doubleClick': function (event, node) { |
159 | - if (node.nodeType != types.ruleNodeType.INPUT.value) { | 160 | + if (node.component.type != types.ruleNodeType.INPUT.value) { |
160 | vm.isEditingRuleNodeLink = false; | 161 | vm.isEditingRuleNodeLink = false; |
161 | vm.editingRuleNodeLink = null; | 162 | vm.editingRuleNodeLink = null; |
162 | vm.isEditingRuleNode = true; | 163 | vm.isEditingRuleNode = true; |
@@ -171,9 +172,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -171,9 +172,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
171 | createEdge: function (event, edge) { | 172 | createEdge: function (event, edge) { |
172 | var deferred = $q.defer(); | 173 | var deferred = $q.defer(); |
173 | var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); | 174 | var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); |
174 | - if (sourceNode.nodeType == types.ruleNodeType.INPUT.value) { | 175 | + if (sourceNode.component.type == types.ruleNodeType.INPUT.value) { |
175 | var destNode = vm.modelservice.nodes.getNodeByConnectorId(edge.destination); | 176 | var destNode = vm.modelservice.nodes.getNodeByConnectorId(edge.destination); |
176 | - if (destNode.nodeType == types.ruleNodeType.RULE_CHAIN.value) { | 177 | + if (destNode.component.type == types.ruleNodeType.RULE_CHAIN.value) { |
177 | deferred.reject(); | 178 | deferred.reject(); |
178 | } else { | 179 | } else { |
179 | var res = $filter('filter')(vm.ruleChainModel.edges, {source: vm.inputConnectorId}); | 180 | var res = $filter('filter')(vm.ruleChainModel.edges, {source: vm.inputConnectorId}); |
@@ -183,7 +184,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -183,7 +184,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
183 | deferred.resolve(edge); | 184 | deferred.resolve(edge); |
184 | } | 185 | } |
185 | } else { | 186 | } else { |
186 | - ruleChainService.getRuleNodeSupportedLinks(sourceNode.type).then( | 187 | + ruleChainService.getRuleNodeSupportedLinks(sourceNode.component.clazz).then( |
187 | (labels) => { | 188 | (labels) => { |
188 | addRuleNodeLink(event, edge, labels).then( | 189 | addRuleNodeLink(event, edge, labels).then( |
189 | (link) => { | 190 | (link) => { |
@@ -209,24 +210,23 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -209,24 +210,23 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
209 | loadRuleChainLibrary(); | 210 | loadRuleChainLibrary(); |
210 | 211 | ||
211 | function loadRuleChainLibrary() { | 212 | function loadRuleChainLibrary() { |
212 | - ruleChainService.getRuleNodeTypes().then( | ||
213 | - (ruleNodeTypes) => { | ||
214 | - for (var i=0;i<ruleNodeTypes.length;i++) { | ||
215 | - var ruleNodeType = ruleNodeTypes[i]; | ||
216 | - var nodeType = ruleNodeType.nodeType; | ||
217 | - var model = vm.ruleNodeTypesModel[nodeType].model; | 213 | + ruleChainService.getRuleNodeComponents().then( |
214 | + (ruleNodeComponents) => { | ||
215 | + for (var i=0;i<ruleNodeComponents.length;i++) { | ||
216 | + var ruleNodeComponent = ruleNodeComponents[i]; | ||
217 | + var componentType = ruleNodeComponent.type; | ||
218 | + var model = vm.ruleNodeTypesModel[componentType].model; | ||
218 | var node = { | 219 | var node = { |
219 | id: model.nodes.length, | 220 | id: model.nodes.length, |
220 | - nodeType: nodeType, | ||
221 | - type: ruleNodeType.type, | 221 | + component: ruleNodeComponent, |
222 | name: '', | 222 | name: '', |
223 | - nodeClass: vm.types.ruleNodeType[nodeType].nodeClass, | ||
224 | - icon: vm.types.ruleNodeType[nodeType].icon, | 223 | + nodeClass: vm.types.ruleNodeType[componentType].nodeClass, |
224 | + icon: vm.types.ruleNodeType[componentType].icon, | ||
225 | x: 30, | 225 | x: 30, |
226 | y: 10+50*model.nodes.length, | 226 | y: 10+50*model.nodes.length, |
227 | connectors: [] | 227 | connectors: [] |
228 | }; | 228 | }; |
229 | - if (nodeType == types.ruleNodeType.RULE_CHAIN.value) { | 229 | + if (componentType == types.ruleNodeType.RULE_CHAIN.value) { |
230 | node.connectors.push( | 230 | node.connectors.push( |
231 | { | 231 | { |
232 | type: flowchartConstants.leftConnectorType, | 232 | type: flowchartConstants.leftConnectorType, |
@@ -249,6 +249,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -249,6 +249,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
249 | } | 249 | } |
250 | model.nodes.push(node); | 250 | model.nodes.push(node); |
251 | } | 251 | } |
252 | + vm.ruleChainLibraryLoaded = true; | ||
252 | prepareRuleChain(); | 253 | prepareRuleChain(); |
253 | } | 254 | } |
254 | ); | 255 | ); |
@@ -273,9 +274,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -273,9 +274,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
273 | vm.ruleChainModel.nodes.push( | 274 | vm.ruleChainModel.nodes.push( |
274 | { | 275 | { |
275 | id: vm.nextNodeID++, | 276 | id: vm.nextNodeID++, |
276 | - type: "Input", | 277 | + component: types.inputNodeComponent, |
277 | name: "", | 278 | name: "", |
278 | - nodeType: types.ruleNodeType.INPUT.value, | ||
279 | nodeClass: types.ruleNodeType.INPUT.nodeClass, | 279 | nodeClass: types.ruleNodeType.INPUT.nodeClass, |
280 | icon: types.ruleNodeType.INPUT.icon, | 280 | icon: types.ruleNodeType.INPUT.icon, |
281 | readonly: true, | 281 | readonly: true, |
@@ -301,20 +301,20 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -301,20 +301,20 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
301 | var nodes = []; | 301 | var nodes = []; |
302 | for (var i=0;i<vm.ruleChainMetaData.nodes.length;i++) { | 302 | for (var i=0;i<vm.ruleChainMetaData.nodes.length;i++) { |
303 | var ruleNode = vm.ruleChainMetaData.nodes[i]; | 303 | var ruleNode = vm.ruleChainMetaData.nodes[i]; |
304 | - var nodeType = ruleChainService.getRuleNodeComponentType(ruleNode.type); | ||
305 | - if (nodeType) { | 304 | + var component = ruleChainService.getRuleNodeComponentByClazz(ruleNode.type); |
305 | + if (component) { | ||
306 | var node = { | 306 | var node = { |
307 | id: vm.nextNodeID++, | 307 | id: vm.nextNodeID++, |
308 | ruleNodeId: ruleNode.id, | 308 | ruleNodeId: ruleNode.id, |
309 | additionalInfo: ruleNode.additionalInfo, | 309 | additionalInfo: ruleNode.additionalInfo, |
310 | configuration: ruleNode.configuration, | 310 | configuration: ruleNode.configuration, |
311 | + debugMode: ruleNode.debugMode, | ||
311 | x: ruleNode.additionalInfo.layoutX, | 312 | x: ruleNode.additionalInfo.layoutX, |
312 | y: ruleNode.additionalInfo.layoutY, | 313 | y: ruleNode.additionalInfo.layoutY, |
313 | - type: ruleNode.type, | 314 | + component: component, |
314 | name: ruleNode.name, | 315 | name: ruleNode.name, |
315 | - nodeType: nodeType, | ||
316 | - nodeClass: vm.types.ruleNodeType[nodeType].nodeClass, | ||
317 | - icon: vm.types.ruleNodeType[nodeType].icon, | 316 | + nodeClass: vm.types.ruleNodeType[component.type].nodeClass, |
317 | + icon: vm.types.ruleNodeType[component.type].icon, | ||
318 | connectors: [ | 318 | connectors: [ |
319 | { | 319 | { |
320 | type: flowchartConstants.leftConnectorType, | 320 | type: flowchartConstants.leftConnectorType, |
@@ -347,7 +347,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -347,7 +347,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
347 | 347 | ||
348 | if (vm.ruleChainMetaData.connections) { | 348 | if (vm.ruleChainMetaData.connections) { |
349 | for (i = 0; i < vm.ruleChainMetaData.connections.length; i++) { | 349 | for (i = 0; i < vm.ruleChainMetaData.connections.length; i++) { |
350 | - var connection = vm.ruleChainMetaData.connections[0]; | 350 | + var connection = vm.ruleChainMetaData.connections[i]; |
351 | var sourceNode = nodes[connection.fromIndex]; | 351 | var sourceNode = nodes[connection.fromIndex]; |
352 | destNode = nodes[connection.toIndex]; | 352 | destNode = nodes[connection.toIndex]; |
353 | if (sourceNode && destNode) { | 353 | if (sourceNode && destNode) { |
@@ -379,9 +379,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -379,9 +379,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
379 | targetRuleChainId: ruleChainConnection.targetRuleChainId.id, | 379 | targetRuleChainId: ruleChainConnection.targetRuleChainId.id, |
380 | x: ruleChainConnection.additionalInfo.layoutX, | 380 | x: ruleChainConnection.additionalInfo.layoutX, |
381 | y: ruleChainConnection.additionalInfo.layoutY, | 381 | y: ruleChainConnection.additionalInfo.layoutY, |
382 | - type: 'Rule chain', | 382 | + component: types.ruleChainNodeComponent, |
383 | name: ruleChain.name, | 383 | name: ruleChain.name, |
384 | - nodeType: vm.types.ruleNodeType.RULE_CHAIN.value, | ||
385 | nodeClass: vm.types.ruleNodeType.RULE_CHAIN.nodeClass, | 384 | nodeClass: vm.types.ruleNodeType.RULE_CHAIN.nodeClass, |
386 | icon: vm.types.ruleNodeType.RULE_CHAIN.icon, | 385 | icon: vm.types.ruleNodeType.RULE_CHAIN.icon, |
387 | connectors: [ | 386 | connectors: [ |
@@ -410,7 +409,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -410,7 +409,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
410 | } | 409 | } |
411 | } | 410 | } |
412 | 411 | ||
413 | - vm.canvasControl.adjustCanvasSize(); | 412 | + if (vm.canvasControl.adjustCanvasSize) { |
413 | + vm.canvasControl.adjustCanvasSize(); | ||
414 | + } | ||
414 | 415 | ||
415 | vm.isDirty = false; | 416 | vm.isDirty = false; |
416 | 417 | ||
@@ -437,15 +438,16 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -437,15 +438,16 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
437 | 438 | ||
438 | for (var i=0;i<vm.ruleChainModel.nodes.length;i++) { | 439 | for (var i=0;i<vm.ruleChainModel.nodes.length;i++) { |
439 | var node = vm.ruleChainModel.nodes[i]; | 440 | var node = vm.ruleChainModel.nodes[i]; |
440 | - if (node.nodeType != types.ruleNodeType.INPUT.value && node.nodeType != types.ruleNodeType.RULE_CHAIN.value) { | 441 | + if (node.component.type != types.ruleNodeType.INPUT.value && node.component.type != types.ruleNodeType.RULE_CHAIN.value) { |
441 | var ruleNode = {}; | 442 | var ruleNode = {}; |
442 | if (node.ruleNodeId) { | 443 | if (node.ruleNodeId) { |
443 | ruleNode.id = node.ruleNodeId; | 444 | ruleNode.id = node.ruleNodeId; |
444 | } | 445 | } |
445 | - ruleNode.type = node.type; | 446 | + ruleNode.type = node.component.clazz; |
446 | ruleNode.name = node.name; | 447 | ruleNode.name = node.name; |
447 | ruleNode.configuration = node.configuration; | 448 | ruleNode.configuration = node.configuration; |
448 | ruleNode.additionalInfo = node.additionalInfo; | 449 | ruleNode.additionalInfo = node.additionalInfo; |
450 | + ruleNode.debugMode = node.debugMode; | ||
449 | if (!ruleNode.additionalInfo) { | 451 | if (!ruleNode.additionalInfo) { |
450 | ruleNode.additionalInfo = {}; | 452 | ruleNode.additionalInfo = {}; |
451 | } | 453 | } |
@@ -465,9 +467,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -465,9 +467,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
465 | var edge = vm.ruleChainModel.edges[i]; | 467 | var edge = vm.ruleChainModel.edges[i]; |
466 | var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); | 468 | var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); |
467 | var destNode = vm.modelservice.nodes.getNodeByConnectorId(edge.destination); | 469 | var destNode = vm.modelservice.nodes.getNodeByConnectorId(edge.destination); |
468 | - if (sourceNode.nodeType != types.ruleNodeType.INPUT.value) { | 470 | + if (sourceNode.component.type != types.ruleNodeType.INPUT.value) { |
469 | var fromIndex = nodes.indexOf(sourceNode); | 471 | var fromIndex = nodes.indexOf(sourceNode); |
470 | - if (destNode.nodeType == types.ruleNodeType.RULE_CHAIN.value) { | 472 | + if (destNode.component.type == types.ruleNodeType.RULE_CHAIN.value) { |
471 | var ruleChainConnection = { | 473 | var ruleChainConnection = { |
472 | fromIndex: fromIndex, | 474 | fromIndex: fromIndex, |
473 | targetRuleChainId: {entityType: vm.types.entityType.rulechain, id: destNode.targetRuleChainId}, | 475 | targetRuleChainId: {entityType: vm.types.entityType.rulechain, id: destNode.targetRuleChainId}, |
@@ -522,7 +524,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | @@ -522,7 +524,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans | ||
522 | type: flowchartConstants.leftConnectorType | 524 | type: flowchartConstants.leftConnectorType |
523 | } | 525 | } |
524 | ); | 526 | ); |
525 | - if (ruleNode.nodeType != types.ruleNodeType.RULE_CHAIN.value) { | 527 | + if (ruleNode.component.type != types.ruleNodeType.RULE_CHAIN.value) { |
526 | ruleNode.connectors.push( | 528 | ruleNode.connectors.push( |
527 | { | 529 | { |
528 | id: vm.nextConnectorID++, | 530 | id: vm.nextConnectorID++, |
@@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
21 | <section class="tb-rulechain-container" flex layout="column"> | 21 | <section class="tb-rulechain-container" flex layout="column"> |
22 | <div class="tb-rulechain-layout" flex layout="row"> | 22 | <div class="tb-rulechain-layout" flex layout="row"> |
23 | <div class="tb-rulechain-library"> | 23 | <div class="tb-rulechain-library"> |
24 | - <md-expansion-panel-group class="tb-rulechain-library-panel-group" md-component-id="libraryPanelGroup" auto-expand="true" multiple> | 24 | + <md-expansion-panel-group ng-if="vm.ruleChainLibraryLoaded" class="tb-rulechain-library-panel-group" md-component-id="libraryPanelGroup" auto-expand="true" multiple> |
25 | <md-expansion-panel md-component-id="{{typeId}}" id="{{typeId}}" ng-repeat="(typeId, typeModel) in vm.ruleNodeTypesModel"> | 25 | <md-expansion-panel md-component-id="{{typeId}}" id="{{typeId}}" ng-repeat="(typeId, typeModel) in vm.ruleNodeTypesModel"> |
26 | <md-expansion-panel-collapsed> | 26 | <md-expansion-panel-collapsed> |
27 | <div class="tb-panel-title" translate>{{vm.types.ruleNodeType[typeId].name}}</div> | 27 | <div class="tb-panel-title" translate>{{vm.types.ruleNodeType[typeId].name}}</div> |
@@ -23,9 +23,9 @@ | @@ -23,9 +23,9 @@ | ||
23 | <fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> | 23 | <fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> |
24 | <md-input-container class="md-block"> | 24 | <md-input-container class="md-block"> |
25 | <label translate>rulenode.type</label> | 25 | <label translate>rulenode.type</label> |
26 | - <input readonly name="type" ng-model="ruleNode.type"> | 26 | + <input readonly name="type" ng-model="ruleNode.component.name"> |
27 | </md-input-container> | 27 | </md-input-container> |
28 | - <section ng-if="ruleNode.nodeType != types.ruleNodeType.RULE_CHAIN.value"> | 28 | + <section ng-if="ruleNode.component.type != types.ruleNodeType.RULE_CHAIN.value"> |
29 | <md-input-container class="md-block"> | 29 | <md-input-container class="md-block"> |
30 | <label translate>rulenode.name</label> | 30 | <label translate>rulenode.name</label> |
31 | <input required name="name" ng-model="ruleNode.name"> | 31 | <input required name="name" ng-model="ruleNode.name"> |
@@ -34,11 +34,16 @@ | @@ -34,11 +34,16 @@ | ||
34 | </div> | 34 | </div> |
35 | </md-input-container> | 35 | </md-input-container> |
36 | <md-input-container class="md-block"> | 36 | <md-input-container class="md-block"> |
37 | + <md-checkbox ng-disabled="$root.loading || !isEdit" aria-label="{{ 'rulenode.debug-mode' | translate }}" | ||
38 | + ng-model="ruleNode.debugMode">{{ 'rulenode.debug-mode' | translate }} | ||
39 | + </md-checkbox> | ||
40 | + </md-input-container> | ||
41 | + <md-input-container class="md-block"> | ||
37 | <label translate>rulenode.description</label> | 42 | <label translate>rulenode.description</label> |
38 | <textarea ng-model="ruleNode.additionalInfo.description" rows="2"></textarea> | 43 | <textarea ng-model="ruleNode.additionalInfo.description" rows="2"></textarea> |
39 | </md-input-container> | 44 | </md-input-container> |
40 | </section> | 45 | </section> |
41 | - <section ng-if="ruleNode.nodeType == types.ruleNodeType.RULE_CHAIN.value"> | 46 | + <section ng-if="ruleNode.component.type == types.ruleNodeType.RULE_CHAIN.value"> |
42 | <tb-entity-autocomplete the-form="theForm" | 47 | <tb-entity-autocomplete the-form="theForm" |
43 | ng-disabled="$root.loading || !isEdit || isReadOnly" | 48 | ng-disabled="$root.loading || !isEdit || isReadOnly" |
44 | tb-required="true" | 49 | tb-required="true" |
@@ -33,7 +33,7 @@ export default function RuleNodeDirective($compile, $templateCache, ruleChainSer | @@ -33,7 +33,7 @@ export default function RuleNodeDirective($compile, $templateCache, ruleChainSer | ||
33 | }; | 33 | }; |
34 | 34 | ||
35 | scope.$watch('ruleNode', function() { | 35 | scope.$watch('ruleNode', function() { |
36 | - if (scope.ruleNode && scope.ruleNode.nodeType == types.ruleNodeType.RULE_CHAIN.value) { | 36 | + if (scope.ruleNode && scope.ruleNode.component.type == types.ruleNodeType.RULE_CHAIN.value) { |
37 | scope.params.targetRuleChainId = scope.ruleNode.targetRuleChainId; | 37 | scope.params.targetRuleChainId = scope.ruleNode.targetRuleChainId; |
38 | watchTargetRuleChain(); | 38 | watchTargetRuleChain(); |
39 | } else { | 39 | } else { |
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | <md-icon aria-label="node-type-icon" flex="15" | 23 | <md-icon aria-label="node-type-icon" flex="15" |
24 | class="material-icons">{{node.icon}}</md-icon> | 24 | class="material-icons">{{node.icon}}</md-icon> |
25 | <div layout="column" flex="85" layout-align="center"> | 25 | <div layout="column" flex="85" layout-align="center"> |
26 | - <span class="tb-node-type">{{ node.type }}</span> | 26 | + <span class="tb-node-type">{{ node.component.name }}</span> |
27 | <span class="tb-node-title" ng-if="node.name">{{ node.name }}</span> | 27 | <span class="tb-node-title" ng-if="node.name">{{ node.name }}</span> |
28 | </div> | 28 | </div> |
29 | <div class="{{flowchartConstants.leftConnectorClass}}"> | 29 | <div class="{{flowchartConstants.leftConnectorClass}}"> |