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 | 71 | import javax.servlet.http.HttpServletResponse; |
72 | 72 | import java.util.List; |
73 | 73 | import java.util.Optional; |
74 | +import java.util.Set; | |
74 | 75 | import java.util.UUID; |
75 | 76 | |
76 | 77 | import static org.thingsboard.server.dao.service.Validator.validateId; |
... | ... | @@ -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 | 493 | List<ComponentDescriptor> checkPluginActionsByPluginClazz(String pluginClazz) throws ThingsboardException { |
484 | 494 | try { |
485 | 495 | checkComponentDescriptorByClazz(pluginClazz); | ... | ... |
... | ... | @@ -21,7 +21,9 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor; |
21 | 21 | import org.thingsboard.server.common.data.plugin.ComponentType; |
22 | 22 | import org.thingsboard.server.exception.ThingsboardException; |
23 | 23 | |
24 | +import java.util.HashSet; | |
24 | 25 | import java.util.List; |
26 | +import java.util.Set; | |
25 | 27 | |
26 | 28 | @RestController |
27 | 29 | @RequestMapping("/api") |
... | ... | @@ -52,6 +54,22 @@ public class ComponentDescriptorController extends BaseController { |
52 | 54 | } |
53 | 55 | |
54 | 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 | 73 | @RequestMapping(value = "/components/actions/{pluginClazz:.+}", method = RequestMethod.GET) |
56 | 74 | @ResponseBody |
57 | 75 | public List<ComponentDescriptor> getPluginActionsByPluginClazz(@PathVariable("pluginClazz") String pluginClazz) throws ThingsboardException { | ... | ... |
... | ... | @@ -204,6 +204,15 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe |
204 | 204 | } |
205 | 205 | |
206 | 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 | 216 | public Optional<ComponentDescriptor> getComponent(String clazz) { |
208 | 217 | return Optional.ofNullable(components.get(clazz)); |
209 | 218 | } | ... | ... |
... | ... | @@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; |
20 | 20 | |
21 | 21 | import java.util.List; |
22 | 22 | import java.util.Optional; |
23 | +import java.util.Set; | |
23 | 24 | |
24 | 25 | /** |
25 | 26 | * @author Andrew Shvayka |
... | ... | @@ -30,6 +31,8 @@ public interface ComponentDiscoveryService { |
30 | 31 | |
31 | 32 | List<ComponentDescriptor> getComponents(ComponentType type); |
32 | 33 | |
34 | + List<ComponentDescriptor> getComponents(Set<ComponentType> types); | |
35 | + | |
33 | 36 | Optional<ComponentDescriptor> getComponent(String clazz); |
34 | 37 | |
35 | 38 | List<ComponentDescriptor> getPluginActions(String pluginClazz); | ... | ... |
... | ... | @@ -26,7 +26,8 @@ function ComponentDescriptorService($http, $q) { |
26 | 26 | var service = { |
27 | 27 | getComponentDescriptorsByType: getComponentDescriptorsByType, |
28 | 28 | getComponentDescriptorByClazz: getComponentDescriptorByClazz, |
29 | - getPluginActionsByPluginClazz: getPluginActionsByPluginClazz | |
29 | + getPluginActionsByPluginClazz: getPluginActionsByPluginClazz, | |
30 | + getComponentDescriptorsByTypes: getComponentDescriptorsByTypes | |
30 | 31 | } |
31 | 32 | |
32 | 33 | return service; |
... | ... | @@ -52,6 +53,41 @@ function ComponentDescriptorService($http, $q) { |
52 | 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 | 91 | function getComponentDescriptorByClazz(componentDescriptorClazz) { |
56 | 92 | var deferred = $q.defer(); |
57 | 93 | if (componentsByClazz[componentDescriptorClazz]) { | ... | ... |
... | ... | @@ -17,9 +17,9 @@ export default angular.module('thingsboard.api.ruleChain', []) |
17 | 17 | .factory('ruleChainService', RuleChainService).name; |
18 | 18 | |
19 | 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 | 24 | var service = { |
25 | 25 | getSystemRuleChains: getSystemRuleChains, |
... | ... | @@ -30,8 +30,8 @@ function RuleChainService($http, $q, $filter, types) { |
30 | 30 | deleteRuleChain: deleteRuleChain, |
31 | 31 | getRuleChainMetaData: getRuleChainMetaData, |
32 | 32 | saveRuleChainMetaData: saveRuleChainMetaData, |
33 | - getRuleNodeTypes: getRuleNodeTypes, | |
34 | - getRuleNodeComponentType: getRuleNodeComponentType, | |
33 | + getRuleNodeComponents: getRuleNodeComponents, | |
34 | + getRuleNodeComponentByClazz: getRuleNodeComponentByClazz, | |
35 | 35 | getRuleNodeSupportedLinks: getRuleNodeSupportedLinks, |
36 | 36 | resolveTargetRuleChains: resolveTargetRuleChains |
37 | 37 | }; |
... | ... | @@ -165,21 +165,18 @@ function RuleChainService($http, $q, $filter, types) { |
165 | 165 | return deferred.promise; |
166 | 166 | } |
167 | 167 | |
168 | - function getRuleNodeTypes() { | |
168 | + function getRuleNodeComponents() { | |
169 | 169 | var deferred = $q.defer(); |
170 | - if (ruleNodeTypes) { | |
171 | - deferred.resolve(ruleNodeTypes); | |
170 | + if (ruleNodeComponents) { | |
171 | + deferred.resolve(ruleNodeComponents); | |
172 | 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 | 182 | deferred.reject(); |
... | ... | @@ -189,10 +186,10 @@ function RuleChainService($http, $q, $filter, types) { |
189 | 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 | 191 | if (res && res.length) { |
195 | - return res[0].nodeType; | |
192 | + return res[0]; | |
196 | 193 | } |
197 | 194 | return null; |
198 | 195 | } |
... | ... | @@ -222,61 +219,8 @@ function RuleChainService($http, $q, $filter, types) { |
222 | 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 | 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 | 471 | ruleNodeType: { |
461 | 472 | FILTER: { |
462 | 473 | value: "FILTER", | ... | ... |
... | ... | @@ -1167,7 +1167,8 @@ export default angular.module('thingsboard.locale', []) |
1167 | 1167 | "select-rulechain": "Select rule chain", |
1168 | 1168 | "no-rulechains-matching": "No rule chains matching '{{entity}}' were found.", |
1169 | 1169 | "rulechain-required": "Rule chain is required", |
1170 | - "management": "Rules management" | |
1170 | + "management": "Rules management", | |
1171 | + "debug-mode": "Debug mode" | |
1171 | 1172 | }, |
1172 | 1173 | "rulenode": { |
1173 | 1174 | "add": "Add rule node", |
... | ... | @@ -1177,6 +1178,7 @@ export default angular.module('thingsboard.locale', []) |
1177 | 1178 | "description": "Description", |
1178 | 1179 | "delete": "Delete rule node", |
1179 | 1180 | "rulenode-details": "Rule node details", |
1181 | + "debug-mode": "Debug mode", | |
1180 | 1182 | "link-details": "Rule node link details", |
1181 | 1183 | "add-link": "Add link", |
1182 | 1184 | "link-label": "Link label", | ... | ... |
... | ... | @@ -42,6 +42,11 @@ |
42 | 42 | </div> |
43 | 43 | </md-input-container> |
44 | 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 | 50 | <label translate>rulechain.description</label> |
46 | 51 | <textarea ng-model="ruleChain.additionalInfo.description" rows="2"></textarea> |
47 | 52 | </md-input-container> | ... | ... |
... | ... | @@ -54,6 +54,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
54 | 54 | }; |
55 | 55 | |
56 | 56 | vm.ruleNodeTypesModel = {}; |
57 | + vm.ruleChainLibraryLoaded = false; | |
57 | 58 | for (var type in types.ruleNodeType) { |
58 | 59 | if (!types.ruleNodeType[type].special) { |
59 | 60 | vm.ruleNodeTypesModel[type] = { |
... | ... | @@ -141,8 +142,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
141 | 142 | vm.editCallbacks = { |
142 | 143 | edgeDoubleClick: function (event, edge) { |
143 | 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 | 147 | (labels) => { |
147 | 148 | vm.isEditingRuleNode = false; |
148 | 149 | vm.editingRuleNode = null; |
... | ... | @@ -156,7 +157,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
156 | 157 | }, |
157 | 158 | nodeCallbacks: { |
158 | 159 | 'doubleClick': function (event, node) { |
159 | - if (node.nodeType != types.ruleNodeType.INPUT.value) { | |
160 | + if (node.component.type != types.ruleNodeType.INPUT.value) { | |
160 | 161 | vm.isEditingRuleNodeLink = false; |
161 | 162 | vm.editingRuleNodeLink = null; |
162 | 163 | vm.isEditingRuleNode = true; |
... | ... | @@ -171,9 +172,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
171 | 172 | createEdge: function (event, edge) { |
172 | 173 | var deferred = $q.defer(); |
173 | 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 | 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 | 178 | deferred.reject(); |
178 | 179 | } else { |
179 | 180 | var res = $filter('filter')(vm.ruleChainModel.edges, {source: vm.inputConnectorId}); |
... | ... | @@ -183,7 +184,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
183 | 184 | deferred.resolve(edge); |
184 | 185 | } |
185 | 186 | } else { |
186 | - ruleChainService.getRuleNodeSupportedLinks(sourceNode.type).then( | |
187 | + ruleChainService.getRuleNodeSupportedLinks(sourceNode.component.clazz).then( | |
187 | 188 | (labels) => { |
188 | 189 | addRuleNodeLink(event, edge, labels).then( |
189 | 190 | (link) => { |
... | ... | @@ -209,24 +210,23 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
209 | 210 | loadRuleChainLibrary(); |
210 | 211 | |
211 | 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 | 219 | var node = { |
219 | 220 | id: model.nodes.length, |
220 | - nodeType: nodeType, | |
221 | - type: ruleNodeType.type, | |
221 | + component: ruleNodeComponent, | |
222 | 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 | 225 | x: 30, |
226 | 226 | y: 10+50*model.nodes.length, |
227 | 227 | connectors: [] |
228 | 228 | }; |
229 | - if (nodeType == types.ruleNodeType.RULE_CHAIN.value) { | |
229 | + if (componentType == types.ruleNodeType.RULE_CHAIN.value) { | |
230 | 230 | node.connectors.push( |
231 | 231 | { |
232 | 232 | type: flowchartConstants.leftConnectorType, |
... | ... | @@ -249,6 +249,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
249 | 249 | } |
250 | 250 | model.nodes.push(node); |
251 | 251 | } |
252 | + vm.ruleChainLibraryLoaded = true; | |
252 | 253 | prepareRuleChain(); |
253 | 254 | } |
254 | 255 | ); |
... | ... | @@ -273,9 +274,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
273 | 274 | vm.ruleChainModel.nodes.push( |
274 | 275 | { |
275 | 276 | id: vm.nextNodeID++, |
276 | - type: "Input", | |
277 | + component: types.inputNodeComponent, | |
277 | 278 | name: "", |
278 | - nodeType: types.ruleNodeType.INPUT.value, | |
279 | 279 | nodeClass: types.ruleNodeType.INPUT.nodeClass, |
280 | 280 | icon: types.ruleNodeType.INPUT.icon, |
281 | 281 | readonly: true, |
... | ... | @@ -301,20 +301,20 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
301 | 301 | var nodes = []; |
302 | 302 | for (var i=0;i<vm.ruleChainMetaData.nodes.length;i++) { |
303 | 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 | 306 | var node = { |
307 | 307 | id: vm.nextNodeID++, |
308 | 308 | ruleNodeId: ruleNode.id, |
309 | 309 | additionalInfo: ruleNode.additionalInfo, |
310 | 310 | configuration: ruleNode.configuration, |
311 | + debugMode: ruleNode.debugMode, | |
311 | 312 | x: ruleNode.additionalInfo.layoutX, |
312 | 313 | y: ruleNode.additionalInfo.layoutY, |
313 | - type: ruleNode.type, | |
314 | + component: component, | |
314 | 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 | 318 | connectors: [ |
319 | 319 | { |
320 | 320 | type: flowchartConstants.leftConnectorType, |
... | ... | @@ -347,7 +347,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
347 | 347 | |
348 | 348 | if (vm.ruleChainMetaData.connections) { |
349 | 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 | 351 | var sourceNode = nodes[connection.fromIndex]; |
352 | 352 | destNode = nodes[connection.toIndex]; |
353 | 353 | if (sourceNode && destNode) { |
... | ... | @@ -379,9 +379,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
379 | 379 | targetRuleChainId: ruleChainConnection.targetRuleChainId.id, |
380 | 380 | x: ruleChainConnection.additionalInfo.layoutX, |
381 | 381 | y: ruleChainConnection.additionalInfo.layoutY, |
382 | - type: 'Rule chain', | |
382 | + component: types.ruleChainNodeComponent, | |
383 | 383 | name: ruleChain.name, |
384 | - nodeType: vm.types.ruleNodeType.RULE_CHAIN.value, | |
385 | 384 | nodeClass: vm.types.ruleNodeType.RULE_CHAIN.nodeClass, |
386 | 385 | icon: vm.types.ruleNodeType.RULE_CHAIN.icon, |
387 | 386 | connectors: [ |
... | ... | @@ -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 | 416 | vm.isDirty = false; |
416 | 417 | |
... | ... | @@ -437,15 +438,16 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
437 | 438 | |
438 | 439 | for (var i=0;i<vm.ruleChainModel.nodes.length;i++) { |
439 | 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 | 442 | var ruleNode = {}; |
442 | 443 | if (node.ruleNodeId) { |
443 | 444 | ruleNode.id = node.ruleNodeId; |
444 | 445 | } |
445 | - ruleNode.type = node.type; | |
446 | + ruleNode.type = node.component.clazz; | |
446 | 447 | ruleNode.name = node.name; |
447 | 448 | ruleNode.configuration = node.configuration; |
448 | 449 | ruleNode.additionalInfo = node.additionalInfo; |
450 | + ruleNode.debugMode = node.debugMode; | |
449 | 451 | if (!ruleNode.additionalInfo) { |
450 | 452 | ruleNode.additionalInfo = {}; |
451 | 453 | } |
... | ... | @@ -465,9 +467,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
465 | 467 | var edge = vm.ruleChainModel.edges[i]; |
466 | 468 | var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); |
467 | 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 | 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 | 473 | var ruleChainConnection = { |
472 | 474 | fromIndex: fromIndex, |
473 | 475 | targetRuleChainId: {entityType: vm.types.entityType.rulechain, id: destNode.targetRuleChainId}, |
... | ... | @@ -522,7 +524,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans |
522 | 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 | 528 | ruleNode.connectors.push( |
527 | 529 | { |
528 | 530 | id: vm.nextConnectorID++, | ... | ... |
... | ... | @@ -21,7 +21,7 @@ |
21 | 21 | <section class="tb-rulechain-container" flex layout="column"> |
22 | 22 | <div class="tb-rulechain-layout" flex layout="row"> |
23 | 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 | 25 | <md-expansion-panel md-component-id="{{typeId}}" id="{{typeId}}" ng-repeat="(typeId, typeModel) in vm.ruleNodeTypesModel"> |
26 | 26 | <md-expansion-panel-collapsed> |
27 | 27 | <div class="tb-panel-title" translate>{{vm.types.ruleNodeType[typeId].name}}</div> | ... | ... |
... | ... | @@ -23,9 +23,9 @@ |
23 | 23 | <fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> |
24 | 24 | <md-input-container class="md-block"> |
25 | 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 | 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 | 29 | <md-input-container class="md-block"> |
30 | 30 | <label translate>rulenode.name</label> |
31 | 31 | <input required name="name" ng-model="ruleNode.name"> |
... | ... | @@ -34,11 +34,16 @@ |
34 | 34 | </div> |
35 | 35 | </md-input-container> |
36 | 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 | 42 | <label translate>rulenode.description</label> |
38 | 43 | <textarea ng-model="ruleNode.additionalInfo.description" rows="2"></textarea> |
39 | 44 | </md-input-container> |
40 | 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 | 47 | <tb-entity-autocomplete the-form="theForm" |
43 | 48 | ng-disabled="$root.loading || !isEdit || isReadOnly" |
44 | 49 | tb-required="true" | ... | ... |
... | ... | @@ -33,7 +33,7 @@ export default function RuleNodeDirective($compile, $templateCache, ruleChainSer |
33 | 33 | }; |
34 | 34 | |
35 | 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 | 37 | scope.params.targetRuleChainId = scope.ruleNode.targetRuleChainId; |
38 | 38 | watchTargetRuleChain(); |
39 | 39 | } else { | ... | ... |
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | <md-icon aria-label="node-type-icon" flex="15" |
24 | 24 | class="material-icons">{{node.icon}}</md-icon> |
25 | 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 | 27 | <span class="tb-node-title" ng-if="node.name">{{ node.name }}</span> |
28 | 28 | </div> |
29 | 29 | <div class="{{flowchartConstants.leftConnectorClass}}"> | ... | ... |