Use ComponentDescriptors in RuleChain UI

This commit is contained in:
Igor Kulikov 2018-03-21 17:34:07 +02:00
parent a5c59e5c88
commit 344f6045a6
14 changed files with 161 additions and 116 deletions

View File

@ -71,6 +71,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.service.Validator.validateId; import static org.thingsboard.server.dao.service.Validator.validateId;
@ -480,6 +481,15 @@ public abstract class BaseController {
} }
} }
List<ComponentDescriptor> checkComponentDescriptorsByTypes(Set<ComponentType> types) throws ThingsboardException {
try {
log.debug("[{}] Lookup component descriptors", types);
return componentDescriptorService.getComponents(types);
} catch (Exception e) {
throw handleException(e, false);
}
}
List<ComponentDescriptor> checkPluginActionsByPluginClazz(String pluginClazz) throws ThingsboardException { List<ComponentDescriptor> checkPluginActionsByPluginClazz(String pluginClazz) throws ThingsboardException {
try { try {
checkComponentDescriptorByClazz(pluginClazz); checkComponentDescriptorByClazz(pluginClazz);

View File

@ -21,7 +21,9 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.exception.ThingsboardException; import org.thingsboard.server.exception.ThingsboardException;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
@RestController @RestController
@RequestMapping("/api") @RequestMapping("/api")
@ -51,6 +53,22 @@ public class ComponentDescriptorController extends BaseController {
} }
} }
@PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')")
@RequestMapping(value = "/components", params = {"componentTypes"}, method = RequestMethod.GET)
@ResponseBody
public List<ComponentDescriptor> getComponentDescriptorsByTypes(@RequestParam("componentTypes") String[] strComponentTypes) throws ThingsboardException {
checkArrayParameter("componentTypes", strComponentTypes);
try {
Set<ComponentType> componentTypes = new HashSet<>();
for (String strComponentType : strComponentTypes) {
componentTypes.add(ComponentType.valueOf(strComponentType));
}
return checkComponentDescriptorsByTypes(componentTypes);
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')")
@RequestMapping(value = "/components/actions/{pluginClazz:.+}", method = RequestMethod.GET) @RequestMapping(value = "/components/actions/{pluginClazz:.+}", method = RequestMethod.GET)
@ResponseBody @ResponseBody

View File

@ -203,6 +203,15 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
return Collections.unmodifiableList(componentsMap.get(type)); return Collections.unmodifiableList(componentsMap.get(type));
} }
@Override
public List<ComponentDescriptor> getComponents(Set<ComponentType> types) {
List<ComponentDescriptor> result = new ArrayList<>();
for (ComponentType type : types) {
result.addAll(componentsMap.get(type));
}
return Collections.unmodifiableList(result);
}
@Override @Override
public Optional<ComponentDescriptor> getComponent(String clazz) { public Optional<ComponentDescriptor> getComponent(String clazz) {
return Optional.ofNullable(components.get(clazz)); return Optional.ofNullable(components.get(clazz));

View File

@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
/** /**
* @author Andrew Shvayka * @author Andrew Shvayka
@ -30,6 +31,8 @@ public interface ComponentDiscoveryService {
List<ComponentDescriptor> getComponents(ComponentType type); List<ComponentDescriptor> getComponents(ComponentType type);
List<ComponentDescriptor> getComponents(Set<ComponentType> types);
Optional<ComponentDescriptor> getComponent(String clazz); Optional<ComponentDescriptor> getComponent(String clazz);
List<ComponentDescriptor> getPluginActions(String pluginClazz); List<ComponentDescriptor> getPluginActions(String pluginClazz);

View File

@ -26,7 +26,8 @@ function ComponentDescriptorService($http, $q) {
var service = { var service = {
getComponentDescriptorsByType: getComponentDescriptorsByType, getComponentDescriptorsByType: getComponentDescriptorsByType,
getComponentDescriptorByClazz: getComponentDescriptorByClazz, getComponentDescriptorByClazz: getComponentDescriptorByClazz,
getPluginActionsByPluginClazz: getPluginActionsByPluginClazz getPluginActionsByPluginClazz: getPluginActionsByPluginClazz,
getComponentDescriptorsByTypes: getComponentDescriptorsByTypes
} }
return service; return service;
@ -52,6 +53,41 @@ function ComponentDescriptorService($http, $q) {
return deferred.promise; return deferred.promise;
} }
function getComponentDescriptorsByTypes(componentTypes) {
var deferred = $q.defer();
var result = [];
for (var i=componentTypes.length-1;i>=0;i--) {
var componentType = componentTypes[i];
if (componentsByType[componentType]) {
result = result.concat(componentsByType[componentType]);
componentTypes.splice(i, 1);
}
}
if (!componentTypes.length) {
deferred.resolve(result);
} else {
var url = '/api/components?componentTypes=' + componentTypes.join(',');
$http.get(url, null).then(function success(response) {
var components = response.data;
for (var i = 0; i < components.length; i++) {
var component = components[i];
var componentsList = componentsByType[component.type];
if (!componentsList) {
componentsList = [];
componentsByType[component.type] = componentsList;
}
componentsList.push(component);
componentsByClazz[component.clazz] = component;
}
result = result.concat(components);
deferred.resolve(components);
}, function fail() {
deferred.reject();
});
}
return deferred.promise;
}
function getComponentDescriptorByClazz(componentDescriptorClazz) { function getComponentDescriptorByClazz(componentDescriptorClazz) {
var deferred = $q.defer(); var deferred = $q.defer();
if (componentsByClazz[componentDescriptorClazz]) { if (componentsByClazz[componentDescriptorClazz]) {

View File

@ -17,9 +17,9 @@ export default angular.module('thingsboard.api.ruleChain', [])
.factory('ruleChainService', RuleChainService).name; .factory('ruleChainService', RuleChainService).name;
/*@ngInject*/ /*@ngInject*/
function RuleChainService($http, $q, $filter, types) { function RuleChainService($http, $q, $filter, types, componentDescriptorService) {
var ruleNodeTypes = null; var ruleNodeComponents = null;
var service = { var service = {
getSystemRuleChains: getSystemRuleChains, getSystemRuleChains: getSystemRuleChains,
@ -30,8 +30,8 @@ function RuleChainService($http, $q, $filter, types) {
deleteRuleChain: deleteRuleChain, deleteRuleChain: deleteRuleChain,
getRuleChainMetaData: getRuleChainMetaData, getRuleChainMetaData: getRuleChainMetaData,
saveRuleChainMetaData: saveRuleChainMetaData, saveRuleChainMetaData: saveRuleChainMetaData,
getRuleNodeTypes: getRuleNodeTypes, getRuleNodeComponents: getRuleNodeComponents,
getRuleNodeComponentType: getRuleNodeComponentType, getRuleNodeComponentByClazz: getRuleNodeComponentByClazz,
getRuleNodeSupportedLinks: getRuleNodeSupportedLinks, getRuleNodeSupportedLinks: getRuleNodeSupportedLinks,
resolveTargetRuleChains: resolveTargetRuleChains resolveTargetRuleChains: resolveTargetRuleChains
}; };
@ -165,21 +165,18 @@ function RuleChainService($http, $q, $filter, types) {
return deferred.promise; return deferred.promise;
} }
function getRuleNodeTypes() { function getRuleNodeComponents() {
var deferred = $q.defer(); var deferred = $q.defer();
if (ruleNodeTypes) { if (ruleNodeComponents) {
deferred.resolve(ruleNodeTypes); deferred.resolve(ruleNodeComponents);
} else { } else {
loadRuleNodeTypes().then( loadRuleNodeComponents().then(
(nodeTypes) => { (components) => {
ruleNodeTypes = nodeTypes; ruleNodeComponents = components;
ruleNodeTypes.push( ruleNodeComponents.push(
{ types.ruleChainNodeComponent
nodeType: types.ruleNodeType.RULE_CHAIN.value,
type: 'Rule chain'
}
); );
deferred.resolve(ruleNodeTypes); deferred.resolve(ruleNodeComponents);
}, },
() => { () => {
deferred.reject(); deferred.reject();
@ -189,10 +186,10 @@ function RuleChainService($http, $q, $filter, types) {
return deferred.promise; return deferred.promise;
} }
function getRuleNodeComponentType(type) { function getRuleNodeComponentByClazz(clazz) {
var res = $filter('filter')(ruleNodeTypes, {type: type}, true); var res = $filter('filter')(ruleNodeComponents, {clazz: clazz}, true);
if (res && res.length) { if (res && res.length) {
return res[0].nodeType; return res[0];
} }
return null; return null;
} }
@ -222,61 +219,8 @@ function RuleChainService($http, $q, $filter, types) {
return deferred.promise; return deferred.promise;
} }
function loadRuleNodeTypes() { function loadRuleNodeComponents() {
var deferred = $q.defer(); return componentDescriptorService.getComponentDescriptorsByTypes(types.ruleNodeTypeComponentTypes);
deferred.resolve(
[
{
nodeType: types.ruleNodeType.FILTER.value,
type: 'Filter'
},
{
nodeType: types.ruleNodeType.FILTER.value,
type: 'Switch'
},
{
nodeType: types.ruleNodeType.ENRICHMENT.value,
type: 'Self'
},
{
nodeType: types.ruleNodeType.ENRICHMENT.value,
type: 'Tenant/Customer'
},
{
nodeType: types.ruleNodeType.ENRICHMENT.value,
type: 'Related Entity'
},
{
nodeType: types.ruleNodeType.ENRICHMENT.value,
type: 'Last Telemetry'
},
{
nodeType: types.ruleNodeType.TRANSFORMATION.value,
type: 'Modify'
},
{
nodeType: types.ruleNodeType.TRANSFORMATION.value,
type: 'New/Update'
},
{
nodeType: types.ruleNodeType.ACTION.value,
type: 'Telemetry'
},
{
nodeType: types.ruleNodeType.ACTION.value,
type: 'RPC call'
},
{
nodeType: types.ruleNodeType.ACTION.value,
type: 'Send email'
},
{
nodeType: types.ruleNodeType.ACTION.value,
type: 'Alarm'
}
]
);
return deferred.promise;
} }

View File

@ -457,6 +457,17 @@ export default angular.module('thingsboard.types', [])
clientSide: false clientSide: false
} }
}, },
ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION"],
ruleChainNodeComponent: {
type: 'RULE_CHAIN',
name: 'Rule chain',
clazz: 'tb.internal.RuleChain'
},
inputNodeComponent: {
type: 'INPUT',
name: 'Input',
clazz: 'tb.internal.Input'
},
ruleNodeType: { ruleNodeType: {
FILTER: { FILTER: {
value: "FILTER", value: "FILTER",

View File

@ -1167,7 +1167,8 @@ export default angular.module('thingsboard.locale', [])
"select-rulechain": "Select rule chain", "select-rulechain": "Select rule chain",
"no-rulechains-matching": "No rule chains matching '{{entity}}' were found.", "no-rulechains-matching": "No rule chains matching '{{entity}}' were found.",
"rulechain-required": "Rule chain is required", "rulechain-required": "Rule chain is required",
"management": "Rules management" "management": "Rules management",
"debug-mode": "Debug mode"
}, },
"rulenode": { "rulenode": {
"add": "Add rule node", "add": "Add rule node",
@ -1177,6 +1178,7 @@ export default angular.module('thingsboard.locale', [])
"description": "Description", "description": "Description",
"delete": "Delete rule node", "delete": "Delete rule node",
"rulenode-details": "Rule node details", "rulenode-details": "Rule node details",
"debug-mode": "Debug mode",
"link-details": "Rule node link details", "link-details": "Rule node link details",
"add-link": "Add link", "add-link": "Add link",
"link-label": "Link label", "link-label": "Link label",

View File

@ -41,6 +41,11 @@
<div translate ng-message="required">rulechain.name-required</div> <div translate ng-message="required">rulechain.name-required</div>
</div> </div>
</md-input-container> </md-input-container>
<md-input-container class="md-block">
<md-checkbox ng-disabled="$root.loading || !isEdit" aria-label="{{ 'rulechain.debug-mode' | translate }}"
ng-model="ruleChain.debugMode">{{ 'rulechain.debug-mode' | translate }}
</md-checkbox>
</md-input-container>
<md-input-container class="md-block"> <md-input-container class="md-block">
<label translate>rulechain.description</label> <label translate>rulechain.description</label>
<textarea ng-model="ruleChain.additionalInfo.description" rows="2"></textarea> <textarea ng-model="ruleChain.additionalInfo.description" rows="2"></textarea>

View File

@ -54,6 +54,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
}; };
vm.ruleNodeTypesModel = {}; vm.ruleNodeTypesModel = {};
vm.ruleChainLibraryLoaded = false;
for (var type in types.ruleNodeType) { for (var type in types.ruleNodeType) {
if (!types.ruleNodeType[type].special) { if (!types.ruleNodeType[type].special) {
vm.ruleNodeTypesModel[type] = { vm.ruleNodeTypesModel[type] = {
@ -141,8 +142,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
vm.editCallbacks = { vm.editCallbacks = {
edgeDoubleClick: function (event, edge) { edgeDoubleClick: function (event, edge) {
var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source);
if (sourceNode.nodeType != types.ruleNodeType.INPUT.value) { if (sourceNode.component.type != types.ruleNodeType.INPUT.value) {
ruleChainService.getRuleNodeSupportedLinks(sourceNode.type).then( ruleChainService.getRuleNodeSupportedLinks(sourceNode.component.clazz).then(
(labels) => { (labels) => {
vm.isEditingRuleNode = false; vm.isEditingRuleNode = false;
vm.editingRuleNode = null; vm.editingRuleNode = null;
@ -156,7 +157,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
}, },
nodeCallbacks: { nodeCallbacks: {
'doubleClick': function (event, node) { 'doubleClick': function (event, node) {
if (node.nodeType != types.ruleNodeType.INPUT.value) { if (node.component.type != types.ruleNodeType.INPUT.value) {
vm.isEditingRuleNodeLink = false; vm.isEditingRuleNodeLink = false;
vm.editingRuleNodeLink = null; vm.editingRuleNodeLink = null;
vm.isEditingRuleNode = true; vm.isEditingRuleNode = true;
@ -171,9 +172,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
createEdge: function (event, edge) { createEdge: function (event, edge) {
var deferred = $q.defer(); var deferred = $q.defer();
var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source);
if (sourceNode.nodeType == types.ruleNodeType.INPUT.value) { if (sourceNode.component.type == types.ruleNodeType.INPUT.value) {
var destNode = vm.modelservice.nodes.getNodeByConnectorId(edge.destination); var destNode = vm.modelservice.nodes.getNodeByConnectorId(edge.destination);
if (destNode.nodeType == types.ruleNodeType.RULE_CHAIN.value) { if (destNode.component.type == types.ruleNodeType.RULE_CHAIN.value) {
deferred.reject(); deferred.reject();
} else { } else {
var res = $filter('filter')(vm.ruleChainModel.edges, {source: vm.inputConnectorId}); var res = $filter('filter')(vm.ruleChainModel.edges, {source: vm.inputConnectorId});
@ -183,7 +184,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
deferred.resolve(edge); deferred.resolve(edge);
} }
} else { } else {
ruleChainService.getRuleNodeSupportedLinks(sourceNode.type).then( ruleChainService.getRuleNodeSupportedLinks(sourceNode.component.clazz).then(
(labels) => { (labels) => {
addRuleNodeLink(event, edge, labels).then( addRuleNodeLink(event, edge, labels).then(
(link) => { (link) => {
@ -209,24 +210,23 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
loadRuleChainLibrary(); loadRuleChainLibrary();
function loadRuleChainLibrary() { function loadRuleChainLibrary() {
ruleChainService.getRuleNodeTypes().then( ruleChainService.getRuleNodeComponents().then(
(ruleNodeTypes) => { (ruleNodeComponents) => {
for (var i=0;i<ruleNodeTypes.length;i++) { for (var i=0;i<ruleNodeComponents.length;i++) {
var ruleNodeType = ruleNodeTypes[i]; var ruleNodeComponent = ruleNodeComponents[i];
var nodeType = ruleNodeType.nodeType; var componentType = ruleNodeComponent.type;
var model = vm.ruleNodeTypesModel[nodeType].model; var model = vm.ruleNodeTypesModel[componentType].model;
var node = { var node = {
id: model.nodes.length, id: model.nodes.length,
nodeType: nodeType, component: ruleNodeComponent,
type: ruleNodeType.type,
name: '', name: '',
nodeClass: vm.types.ruleNodeType[nodeType].nodeClass, nodeClass: vm.types.ruleNodeType[componentType].nodeClass,
icon: vm.types.ruleNodeType[nodeType].icon, icon: vm.types.ruleNodeType[componentType].icon,
x: 30, x: 30,
y: 10+50*model.nodes.length, y: 10+50*model.nodes.length,
connectors: [] connectors: []
}; };
if (nodeType == types.ruleNodeType.RULE_CHAIN.value) { if (componentType == types.ruleNodeType.RULE_CHAIN.value) {
node.connectors.push( node.connectors.push(
{ {
type: flowchartConstants.leftConnectorType, type: flowchartConstants.leftConnectorType,
@ -249,6 +249,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
} }
model.nodes.push(node); model.nodes.push(node);
} }
vm.ruleChainLibraryLoaded = true;
prepareRuleChain(); prepareRuleChain();
} }
); );
@ -273,9 +274,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
vm.ruleChainModel.nodes.push( vm.ruleChainModel.nodes.push(
{ {
id: vm.nextNodeID++, id: vm.nextNodeID++,
type: "Input", component: types.inputNodeComponent,
name: "", name: "",
nodeType: types.ruleNodeType.INPUT.value,
nodeClass: types.ruleNodeType.INPUT.nodeClass, nodeClass: types.ruleNodeType.INPUT.nodeClass,
icon: types.ruleNodeType.INPUT.icon, icon: types.ruleNodeType.INPUT.icon,
readonly: true, readonly: true,
@ -301,20 +301,20 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
var nodes = []; var nodes = [];
for (var i=0;i<vm.ruleChainMetaData.nodes.length;i++) { for (var i=0;i<vm.ruleChainMetaData.nodes.length;i++) {
var ruleNode = vm.ruleChainMetaData.nodes[i]; var ruleNode = vm.ruleChainMetaData.nodes[i];
var nodeType = ruleChainService.getRuleNodeComponentType(ruleNode.type); var component = ruleChainService.getRuleNodeComponentByClazz(ruleNode.type);
if (nodeType) { if (component) {
var node = { var node = {
id: vm.nextNodeID++, id: vm.nextNodeID++,
ruleNodeId: ruleNode.id, ruleNodeId: ruleNode.id,
additionalInfo: ruleNode.additionalInfo, additionalInfo: ruleNode.additionalInfo,
configuration: ruleNode.configuration, configuration: ruleNode.configuration,
debugMode: ruleNode.debugMode,
x: ruleNode.additionalInfo.layoutX, x: ruleNode.additionalInfo.layoutX,
y: ruleNode.additionalInfo.layoutY, y: ruleNode.additionalInfo.layoutY,
type: ruleNode.type, component: component,
name: ruleNode.name, name: ruleNode.name,
nodeType: nodeType, nodeClass: vm.types.ruleNodeType[component.type].nodeClass,
nodeClass: vm.types.ruleNodeType[nodeType].nodeClass, icon: vm.types.ruleNodeType[component.type].icon,
icon: vm.types.ruleNodeType[nodeType].icon,
connectors: [ connectors: [
{ {
type: flowchartConstants.leftConnectorType, type: flowchartConstants.leftConnectorType,
@ -347,7 +347,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
if (vm.ruleChainMetaData.connections) { if (vm.ruleChainMetaData.connections) {
for (i = 0; i < vm.ruleChainMetaData.connections.length; i++) { for (i = 0; i < vm.ruleChainMetaData.connections.length; i++) {
var connection = vm.ruleChainMetaData.connections[0]; var connection = vm.ruleChainMetaData.connections[i];
var sourceNode = nodes[connection.fromIndex]; var sourceNode = nodes[connection.fromIndex];
destNode = nodes[connection.toIndex]; destNode = nodes[connection.toIndex];
if (sourceNode && destNode) { if (sourceNode && destNode) {
@ -379,9 +379,8 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
targetRuleChainId: ruleChainConnection.targetRuleChainId.id, targetRuleChainId: ruleChainConnection.targetRuleChainId.id,
x: ruleChainConnection.additionalInfo.layoutX, x: ruleChainConnection.additionalInfo.layoutX,
y: ruleChainConnection.additionalInfo.layoutY, y: ruleChainConnection.additionalInfo.layoutY,
type: 'Rule chain', component: types.ruleChainNodeComponent,
name: ruleChain.name, name: ruleChain.name,
nodeType: vm.types.ruleNodeType.RULE_CHAIN.value,
nodeClass: vm.types.ruleNodeType.RULE_CHAIN.nodeClass, nodeClass: vm.types.ruleNodeType.RULE_CHAIN.nodeClass,
icon: vm.types.ruleNodeType.RULE_CHAIN.icon, icon: vm.types.ruleNodeType.RULE_CHAIN.icon,
connectors: [ connectors: [
@ -410,7 +409,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
} }
} }
vm.canvasControl.adjustCanvasSize(); if (vm.canvasControl.adjustCanvasSize) {
vm.canvasControl.adjustCanvasSize();
}
vm.isDirty = false; vm.isDirty = false;
@ -437,15 +438,16 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
for (var i=0;i<vm.ruleChainModel.nodes.length;i++) { for (var i=0;i<vm.ruleChainModel.nodes.length;i++) {
var node = vm.ruleChainModel.nodes[i]; var node = vm.ruleChainModel.nodes[i];
if (node.nodeType != types.ruleNodeType.INPUT.value && node.nodeType != types.ruleNodeType.RULE_CHAIN.value) { if (node.component.type != types.ruleNodeType.INPUT.value && node.component.type != types.ruleNodeType.RULE_CHAIN.value) {
var ruleNode = {}; var ruleNode = {};
if (node.ruleNodeId) { if (node.ruleNodeId) {
ruleNode.id = node.ruleNodeId; ruleNode.id = node.ruleNodeId;
} }
ruleNode.type = node.type; ruleNode.type = node.component.clazz;
ruleNode.name = node.name; ruleNode.name = node.name;
ruleNode.configuration = node.configuration; ruleNode.configuration = node.configuration;
ruleNode.additionalInfo = node.additionalInfo; ruleNode.additionalInfo = node.additionalInfo;
ruleNode.debugMode = node.debugMode;
if (!ruleNode.additionalInfo) { if (!ruleNode.additionalInfo) {
ruleNode.additionalInfo = {}; ruleNode.additionalInfo = {};
} }
@ -465,9 +467,9 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
var edge = vm.ruleChainModel.edges[i]; var edge = vm.ruleChainModel.edges[i];
var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source); var sourceNode = vm.modelservice.nodes.getNodeByConnectorId(edge.source);
var destNode = vm.modelservice.nodes.getNodeByConnectorId(edge.destination); var destNode = vm.modelservice.nodes.getNodeByConnectorId(edge.destination);
if (sourceNode.nodeType != types.ruleNodeType.INPUT.value) { if (sourceNode.component.type != types.ruleNodeType.INPUT.value) {
var fromIndex = nodes.indexOf(sourceNode); var fromIndex = nodes.indexOf(sourceNode);
if (destNode.nodeType == types.ruleNodeType.RULE_CHAIN.value) { if (destNode.component.type == types.ruleNodeType.RULE_CHAIN.value) {
var ruleChainConnection = { var ruleChainConnection = {
fromIndex: fromIndex, fromIndex: fromIndex,
targetRuleChainId: {entityType: vm.types.entityType.rulechain, id: destNode.targetRuleChainId}, targetRuleChainId: {entityType: vm.types.entityType.rulechain, id: destNode.targetRuleChainId},
@ -522,7 +524,7 @@ export function RuleChainController($stateParams, $scope, $q, $mdUtil, $mdExpans
type: flowchartConstants.leftConnectorType type: flowchartConstants.leftConnectorType
} }
); );
if (ruleNode.nodeType != types.ruleNodeType.RULE_CHAIN.value) { if (ruleNode.component.type != types.ruleNodeType.RULE_CHAIN.value) {
ruleNode.connectors.push( ruleNode.connectors.push(
{ {
id: vm.nextConnectorID++, id: vm.nextConnectorID++,

View File

@ -21,7 +21,7 @@
<section class="tb-rulechain-container" flex layout="column"> <section class="tb-rulechain-container" flex layout="column">
<div class="tb-rulechain-layout" flex layout="row"> <div class="tb-rulechain-layout" flex layout="row">
<div class="tb-rulechain-library"> <div class="tb-rulechain-library">
<md-expansion-panel-group class="tb-rulechain-library-panel-group" md-component-id="libraryPanelGroup" auto-expand="true" multiple> <md-expansion-panel-group ng-if="vm.ruleChainLibraryLoaded" class="tb-rulechain-library-panel-group" md-component-id="libraryPanelGroup" auto-expand="true" multiple>
<md-expansion-panel md-component-id="{{typeId}}" id="{{typeId}}" ng-repeat="(typeId, typeModel) in vm.ruleNodeTypesModel"> <md-expansion-panel md-component-id="{{typeId}}" id="{{typeId}}" ng-repeat="(typeId, typeModel) in vm.ruleNodeTypesModel">
<md-expansion-panel-collapsed> <md-expansion-panel-collapsed>
<div class="tb-panel-title" translate>{{vm.types.ruleNodeType[typeId].name}}</div> <div class="tb-panel-title" translate>{{vm.types.ruleNodeType[typeId].name}}</div>

View File

@ -23,9 +23,9 @@
<fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> <fieldset ng-disabled="$root.loading || !isEdit || isReadOnly">
<md-input-container class="md-block"> <md-input-container class="md-block">
<label translate>rulenode.type</label> <label translate>rulenode.type</label>
<input readonly name="type" ng-model="ruleNode.type"> <input readonly name="type" ng-model="ruleNode.component.name">
</md-input-container> </md-input-container>
<section ng-if="ruleNode.nodeType != types.ruleNodeType.RULE_CHAIN.value"> <section ng-if="ruleNode.component.type != types.ruleNodeType.RULE_CHAIN.value">
<md-input-container class="md-block"> <md-input-container class="md-block">
<label translate>rulenode.name</label> <label translate>rulenode.name</label>
<input required name="name" ng-model="ruleNode.name"> <input required name="name" ng-model="ruleNode.name">
@ -33,12 +33,17 @@
<div translate ng-message="required">rulenode.name-required</div> <div translate ng-message="required">rulenode.name-required</div>
</div> </div>
</md-input-container> </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>
<md-input-container class="md-block"> <md-input-container class="md-block">
<label translate>rulenode.description</label> <label translate>rulenode.description</label>
<textarea ng-model="ruleNode.additionalInfo.description" rows="2"></textarea> <textarea ng-model="ruleNode.additionalInfo.description" rows="2"></textarea>
</md-input-container> </md-input-container>
</section> </section>
<section ng-if="ruleNode.nodeType == types.ruleNodeType.RULE_CHAIN.value"> <section ng-if="ruleNode.component.type == types.ruleNodeType.RULE_CHAIN.value">
<tb-entity-autocomplete the-form="theForm" <tb-entity-autocomplete the-form="theForm"
ng-disabled="$root.loading || !isEdit || isReadOnly" ng-disabled="$root.loading || !isEdit || isReadOnly"
tb-required="true" tb-required="true"

View File

@ -33,7 +33,7 @@ export default function RuleNodeDirective($compile, $templateCache, ruleChainSer
}; };
scope.$watch('ruleNode', function() { scope.$watch('ruleNode', function() {
if (scope.ruleNode && scope.ruleNode.nodeType == types.ruleNodeType.RULE_CHAIN.value) { if (scope.ruleNode && scope.ruleNode.component.type == types.ruleNodeType.RULE_CHAIN.value) {
scope.params.targetRuleChainId = scope.ruleNode.targetRuleChainId; scope.params.targetRuleChainId = scope.ruleNode.targetRuleChainId;
watchTargetRuleChain(); watchTargetRuleChain();
} else { } else {

View File

@ -23,7 +23,7 @@
<md-icon aria-label="node-type-icon" flex="15" <md-icon aria-label="node-type-icon" flex="15"
class="material-icons">{{node.icon}}</md-icon> class="material-icons">{{node.icon}}</md-icon>
<div layout="column" flex="85" layout-align="center"> <div layout="column" flex="85" layout-align="center">
<span class="tb-node-type">{{ node.type }}</span> <span class="tb-node-type">{{ node.component.name }}</span>
<span class="tb-node-title" ng-if="node.name">{{ node.name }}</span> <span class="tb-node-title" ng-if="node.name">{{ node.name }}</span>
</div> </div>
<div class="{{flowchartConstants.leftConnectorClass}}"> <div class="{{flowchartConstants.leftConnectorClass}}">