aboutsummaryrefslogtreecommitdiffstats
path: root/sdc-workflow-designer-ui/src/app/services
diff options
context:
space:
mode:
authorLvbo163 <lv.bo163@zte.com.cn>2018-01-10 15:05:39 +0800
committerLvbo163 <lv.bo163@zte.com.cn>2018-01-10 15:05:39 +0800
commit38dfd59a8b5d05266e5567f79dcf30fd10ef7c54 (patch)
tree043a724663d3324ce80cc546a241898e99796897 /sdc-workflow-designer-ui/src/app/services
parenteb2d1c385e5c3d96e770b776f74ddbde9f2b133f (diff)
split element by type
split elements by type in toolbar Issue-ID: SDC-895 Change-Id: I0254c9c5f938df80942d60ffefe4b8577c788233 Signed-off-by: Lvbo163 <lv.bo163@zte.com.cn>
Diffstat (limited to 'sdc-workflow-designer-ui/src/app/services')
-rw-r--r--sdc-workflow-designer-ui/src/app/services/broadcast.service.ts12
-rw-r--r--sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts2
-rw-r--r--sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts589
-rw-r--r--sdc-workflow-designer-ui/src/app/services/model.service.ts366
-rw-r--r--sdc-workflow-designer-ui/src/app/services/rest.service.ts168
-rw-r--r--sdc-workflow-designer-ui/src/app/services/workflow.service.ts2
6 files changed, 944 insertions, 195 deletions
diff --git a/sdc-workflow-designer-ui/src/app/services/broadcast.service.ts b/sdc-workflow-designer-ui/src/app/services/broadcast.service.ts
index dd75c45c..544c2a70 100644
--- a/sdc-workflow-designer-ui/src/app/services/broadcast.service.ts
+++ b/sdc-workflow-designer-ui/src/app/services/broadcast.service.ts
@@ -15,6 +15,8 @@ import { Subject } from 'rxjs/Subject';
import { WorkflowNode } from '../model/workflow/workflow-node';
import { SequenceFlow } from "../model/workflow/sequence-flow";
import { PlanModel } from "../model/workflow/plan-model";
+import { WorkflowElement } from '../model/workflow/workflow-element';
+import { RestConfig } from '../model/rest-config';
/**
* BroadcastService
@@ -30,15 +32,21 @@ export class BroadcastService {
public workflows = new Subject<Map<number, any>>();
public workflows$ = this.workflows.asObservable();
- public workflow = new Subject<PlanModel>();
- public workflow$ = this.workflow.asObservable();
+ public planModel = new Subject<PlanModel>();
+ public planModel$ = this.planModel.asObservable();
public showProperty = new Subject<boolean>();
public showProperty$ = this.showProperty.asObservable();
+ public updateModelRestConfig = new Subject<RestConfig[]>();
+ public updateModelRestConfig$ = this.updateModelRestConfig.asObservable();
+
public saveEvent = new Subject<string>();
public saveEvent$ = this.saveEvent.asObservable();
+ public selectedElement = new Subject<WorkflowElement[]>();
+ public selectedElement$ = this.selectedElement.asObservable();
+
public nodeProperty = new Subject<WorkflowNode>();
public nodeProperty$ = this.nodeProperty.asObservable();
diff --git a/sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts b/sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts
index 084c0551..5b2750b1 100644
--- a/sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts
+++ b/sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts
@@ -1,2 +1,2 @@
-export const workflowFJH = {"id":"fjh","name":"fjh","nodes":[{"id":"node0","name":"startEvent","type":"startEvent","position":{"top":31,"left":31,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node0","targetRef":"node23"}],"parameters":[{"name":"vlCount","value":"","valueSource":"String","type":"String"},{"name":"vnfCount","value":"","valueSource":"String","type":"String"},{"name":"sfcCount","value":"","valueSource":"String","type":"String"},{"name":"object_context","value":"","valueSource":"String","type":"String"},{"name":"nsInstanceId","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForNs","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForVnf","value":"","valueSource":"String","type":"String"},{"name":"jobId","value":"","valueSource":"String","type":"String"},{"name":"sdnControllerId","value":"","valueSource":"String","type":"String"},{"name":"templateid","value":"","valueSource":"String","type":"String"},{"name":"instanceid","value":"","valueSource":"String","type":"String"},{"name":"sdnolcmurl","value":"","valueSource":"String","type":"String"},{"name":"statusurl","value":"","valueSource":"String","type":"String"}]},{"id":"node1","name":"endEvent","type":"endEvent","position":{"top":668,"left":955,"width":200,"height":100},"sequenceFlows":[]},{"id":"node2","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":120,"left":169,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node2","targetRef":"node3","condition":"${ vl_index <= vlCount and vl_status='active' }","name":"未完成"},{"sourceRef":"node2","targetRef":"node4","condition":"!( vl_index <= vlCount and vl_status='active' )","name":"创建完成"}]},{"id":"node3","name":"createVL","type":"restTask","position":{"top":213,"left":142,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node3","targetRef":"node11"}],"produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"body","valueSource":"String","type":"String","position":"body","schema":{"$ref":"#/definitions/VlPostRequest"}}],"responses":[{"description":"","schema":{"$ref":"#/definitions/VlPostResponse"}}],"serviceName":"nslcm","serviceVersion":"v1","url":"/ns/vls","method":"post"},{"id":"node4","name":"restTask","type":"restTask","position":{"top":115,"left":358,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node4","targetRef":"node5"}],"produces":[],"consumes":[],"parameters":[],"responses":[],"serviceName":"nslcm","serviceVersion":"v1","url":"","method":""},{"id":"node5","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":212,"left":383,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node5","targetRef":"node6","condition":"未完成"},{"sourceRef":"node5","targetRef":"node12","condition":"创建完成"}]},{"id":"node6","name":"createVNF","type":"restTask","position":{"top":306,"left":352,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node6","targetRef":"node7"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node7","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":558,"left":443,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node7","targetRef":"node8"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node8","name":"query_vnf nslcm","type":"restTask","position":{"top":639,"left":216,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node8","targetRef":"node9"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node9","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":539,"left":264,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node9","targetRef":"node7","condition":"未完成"},{"sourceRef":"node9","targetRef":"node10","condition":"已完成"}]},{"id":"node10","name":"scriptTask","type":"scriptTask","position":{"top":303,"left":239,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node10","targetRef":"node5"}]},{"id":"node11","name":"scriptTask","type":"scriptTask","position":{"top":207,"left":34,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node11","targetRef":"node2"}]},{"id":"node12","name":"restTask","type":"restTask","position":{"top":205,"left":732,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node12","targetRef":"node13"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node13","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":287,"left":757,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node13","targetRef":"node14","condition":"未结束"},{"sourceRef":"node13","targetRef":"node18","condition":"已结束"}]},{"id":"node14","name":"createSfc","type":"restTask","position":{"top":440,"left":726,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node14","targetRef":"node15"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node15","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":551,"left":754,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node15","targetRef":"node16"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node16","name":"restTask","type":"restTask","position":{"top":642,"left":589,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node16","targetRef":"node17"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node17","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":551,"left":614,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node17","targetRef":"node15","condition":"未结束"},{"sourceRef":"node17","targetRef":"node19","condition":"已结束"}]},{"id":"node18","name":"restTask","type":"restTask","position":{"top":282,"left":927,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node18","targetRef":"node20"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node19","name":"scriptTask","type":"scriptTask","position":{"top":275,"left":588,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node19","targetRef":"node13"}]},{"id":"node20","name":"Assign_all_status","type":"scriptTask","position":{"top":380,"left":928,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node20","targetRef":"node21"}]},{"id":"node21","name":"post_do","type":"restTask","position":{"top":497,"left":929,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node21","targetRef":"node22"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node22","name":"jobstatus","type":"restTask","position":{"top":586,"left":927,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node22","targetRef":"node1"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node23","name":"scriptTask","type":"scriptTask","position":{"top":16,"left":143,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node23","targetRef":"node2"}],"scriptFormate":"javascript","script":"execution.setVariable(\"vl_index\", 1);\nexecution.setVariable(\"vl_status\", \"active\");"}],"configs":{"microservices":[{"name":"nslcm","version":"v1","swaggerJson":"{\"info\":{\"version\":\"1.0.0\",\"contact\":{\"url\":\"https://gerrit.onap.org/r/#/admin/projects/vfc/nfvo/lcm\",\"name\":\"ONAP VFC team\",\"email\":\"onap-discuss@lists.onap.org\"},\"description\":\"VFC Network Service Lifecycle Management Rest API.\",\"title\":\"ONAP VFC Network Service Lifecycle Management API\"},\"paths\":{\"/ns/sfcs/{sfcInstId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteResponse\"}},\"404\":{\"description\":\"the sfc instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"sfcInstId\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"delete sfc\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_sfc\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/SfcInfo\"}},\"404\":{\"description\":\"the sfc instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"sfc instance id\",\"required\":true,\"type\":\"string\",\"name\":\"sfcInstId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"query the specified sfc info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_sfc\"}},\"/ns/{nsInstanceId}/postdeal\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NSInstPostDetailRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"postdeal\"],\"summary\":\"ns postdeal\",\"consumes\":[\"application/json\"],\"operationId\":\"ns_postdeal\"}},\"/ns/vnfs\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/VnfPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/VnfPostRequest\"},\"description\":\"instantiate request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"vnf create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_vnf\"}},\"/ns/{ns_instance_id}/heal\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"},{\"schema\":{\"$ref\":\"#/definitions/NsHealRequest\"},\"description\":\"healVnfData\",\"required\":true,\"name\":\"healVnfData\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns heal\",\"summary\":\"ns heal\",\"operationId\":\"ns_heal\"}},\"/jobs/{jobId}\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"jobId\"},{\"schema\":{\"$ref\":\"#/definitions/JobProgressRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"tags\":[\"job\"],\"description\":\"\",\"summary\":\"jobstatus\",\"operationId\":\"post_jobprogress\"},\"get\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobDetailInfo\"}}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"job Id\",\"in\":\"path\",\"name\":\"jobId\"},{\"required\":true,\"type\":\"string\",\"description\":\"job response message id\",\"in\":\"query\",\"name\":\"responseId\"}],\"tags\":[\"job\"],\"description\":\"\",\"summary\":\"jobstatus\",\"operationId\":\"get_jobstatus\"}},\"/ns/vls/{vlId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteVlResponse\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"vlId\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"delete vl\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_vl\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/VlInfo\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"vl instance id\",\"required\":true,\"type\":\"string\",\"name\":\"vlId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"query the specified vl info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_vl\"}},\"/ns/vls\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/VlPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/VlPostRequest\"},\"description\":\"instantiate request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"vl create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_vl\"}},\"/ns/sfcs\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/SfcPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/SfcPostRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"sfc create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_sfc\"}},\"/ns/{ns_instance_id}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"The NS instance resource and the associated NS identifier were deleted successfully.\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"}],\"tags\":[\"ns\"],\"description\":\"ns delete\",\"summary\":\"ns delete\",\"operationId\":\"ns_delete\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsInstanceInfo\"}}},\"parameters\":[],\"tags\":[\"ns\"],\"description\":\"ns get\",\"summary\":\"ns get\",\"operationId\":\"ns_instance_get\"}},\"/ns/vnfs/{vnfInstId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteResponse\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"vnfInstId\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"delete vnf\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_vnf\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/VnfInfo\"}},\"404\":{\"description\":\"the vnf instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"vnf instance id\",\"required\":true,\"type\":\"string\",\"name\":\"vnfInstId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"query the specified vnf info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_vnf\"}},\"/ns\":{\"post\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsCreateResponse\"}}},\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/NsCreateRequest\"},\"description\":\"NS Instance Create Request\",\"required\":true,\"name\":\"NSCreateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns create\",\"summary\":\"ns create\",\"operationId\":\"ns_create\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsInstancesInfo\"}}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"job response message id\",\"in\":\"query\",\"name\":\"csarId\"}],\"tags\":[\"ns\"],\"description\":\"ns get\",\"summary\":\"ns get\",\"operationId\":\"ns_instantces_get\"}},\"/ns/{ns_instance_id}/terminate\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"},{\"schema\":{\"$ref\":\"#/definitions/NsTerminateRequest\"},\"description\":\"NsTerminateRequest\",\"required\":true,\"name\":\"NsTerminateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns terminate\",\"summary\":\"ns terminate\",\"operationId\":\"ns_terminate\"}},\"/ns/{nsInstanceId}/scale\":{\"post\":{\"responses\":{\"200\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"201\":{\"description\":\"Invalid Request\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NsScaleRequest\"},\"description\":\"Scale NS Request Body\",\"required\":true,\"name\":\"ScaleNSRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns scale\",\"summary\":\"ns scale\",\"operationId\":\"ns_scale\"}},\"/mandb/{modelName}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"The tables were deleted successfully.\"}},\"description\":\"ns table delete\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"model Name.\",\"in\":\"path\",\"name\":\"modelName\"}],\"produces\":[\"application/json\"],\"tags\":[\"db\"],\"summary\":\"ns table delete\",\"consumes\":[\"application/json\"],\"operationId\":\"ns_table_delete\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/TableInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"query ns table info\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"model Name.\",\"in\":\"path\",\"name\":\"modelName\"}],\"produces\":[\"application/json\"],\"tags\":[\"db\"],\"summary\":\"query ns table info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_ns_table\"}},\"/ns/{nsInstanceId}/Instantiate\":{\"post\":{\"responses\":{\"200\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"201\":{\"description\":\"Invalid Request\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NsInstantiateRequest\"},\"description\":\"NS Instantiate Request Body\",\"required\":true,\"name\":\"NSInstantiateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns Instantiate\",\"summary\":\"ns Instantiate\",\"operationId\":\"ns_Instantiate\"}}},\"schemes\":[\"http\",\"https\"],\"produces\":[\"application/json\"],\"basePath\":\"/api/nslcm/v1\",\"definitions\":{\"NsInstanceInfo\":{\"type\":\"object\",\"properties\":{\"nsState\":{\"type\":\"string\"},\"vnfInfo\":{\"items\":{\"$ref\":\"#/definitions/vnfInfo\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"nsdId\":{\"type\":\"string\"},\"vlInfo\":{\"items\":{\"$ref\":\"#/definitions/vlInfo\"},\"type\":\"array\"},\"nsName\":{\"type\":\"string\"},\"vnffgInfo\":{\"items\":{\"$ref\":\"#/definitions/vnffgInfo\"},\"type\":\"array\"},\"description\":{\"type\":\"string\"}}},\"JobDetailInfo\":{\"type\":\"object\",\"properties\":{\"responseDescriptor\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"},\"responseHistoryList\":{\"items\":{\"$ref\":\"#/definitions/jobResponseInfo\"},\"type\":\"array\"},\"responseId\":{\"type\":\"string\"},\"errorCode\":{\"type\":\"string\"},\"progress\":{\"type\":\"string\"},\"statusDescription\":{\"type\":\"string\"}}},\"jobId\":{\"type\":\"string\"}}},\"VnfInfo\":{\"type\":\"object\",\"properties\":{\"vnfInstId\":{\"type\":\"string\"},\"vnfName\":{\"type\":\"string\"},\"vnfStatus\":{\"type\":\"string\"}}},\"DeleteResponse\":{\"type\":\"object\",\"properties\":{\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"NsHealRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceId\":{\"type\":\"string\"},\"cause\":{\"type\":\"string\"},\"additionalParams\":{\"type\":\"object\",\"properties\":{\"action\":{\"type\":\"string\"},\"actionvminfo\":{\"type\":\"object\",\"properties\":{\"vmname\":{\"type\":\"string\"},\"vmid\":{\"type\":\"string\"}}}}}}},\"NsScaleRequest\":{\"type\":\"object\",\"properties\":{\"scaleNsByStepsData\":{\"$ref\":\"#/definitions/NsScaleByStepsData\"},\"scaleType\":{\"type\":\"string\"}}},\"jobResponseInfo\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"},\"progress\":{\"type\":\"string\"},\"responseId\":{\"type\":\"string\"},\"statusDescription\":{\"type\":\"string\"},\"errorCode\":{\"type\":\"string\"}}},\"NSInstPostDetailRequest\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"}}},\"VlInfo\":{\"type\":\"object\",\"properties\":{\"vlId\":{\"type\":\"string\"},\"vlStatus\":{\"type\":\"string\"},\"vlName\":{\"type\":\"string\"}}},\"VnfPostResponse\":{\"type\":\"object\",\"properties\":{\"vnfInstId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"}}},\"NsCreateRequest\":{\"type\":\"object\",\"properties\":{\"nsName\":{\"type\":\"string\"},\"csarId\":{\"type\":\"string\",\"description\":\"the NS package ID\"},\"description\":{\"type\":\"string\"}}},\"VlPostResponse\":{\"type\":\"object\",\"properties\":{\"vlId\":{\"type\":\"string\"},\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"SfcPostRequest\":{\"type\":\"object\",\"properties\":{\"sdnControllerId\":{\"type\":\"string\"},\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"fpindex\":{\"type\":\"string\"}}},\"NsTerminateRequest\":{\"type\":\"object\",\"properties\":{\"gracefulTerminationTimeout\":{\"type\":\"string\"},\"terminationType\":{\"type\":\"string\"}}},\"JobProgressRequest\":{\"type\":\"object\",\"properties\":{\"progress\":{\"type\":\"string\"},\"errcode\":{\"type\":\"string\"},\"desc\":{\"type\":\"string\"}}},\"SfcInfo\":{\"type\":\"object\",\"properties\":{\"sfcName\":{\"type\":\"string\"},\"sfcInstId\":{\"type\":\"string\"},\"sfcStatus\":{\"type\":\"string\"}}},\"vnfInfo\":{\"type\":\"object\",\"properties\":{\"vnfInstanceId\":{\"type\":\"string\"},\"vnfdId\":{\"type\":\"string\"},\"vnfInstanceName\":{\"type\":\"string\"}}},\"LocationConstraint\":{\"type\":\"object\",\"properties\":{\"locationConstraints\":{\"type\":\"object\",\"properties\":{\"vimid\":{\"type\":\"string\"}}},\"vnfProfileId\":{\"type\":\"string\"}}},\"NsCreateResponse\":{\"type\":\"object\",\"properties\":{\"nsInstanceId\":{\"type\":\"string\"}}},\"VlPostRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"flavourId\":{\"type\":\"string\"},\"pnfInfo\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"extNSVirtualLink\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nestedNsInstanceId\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"jobId\":{\"type\":\"string\"},\"locationConstraints\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"vlIndex\":{\"type\":\"string\"}}},\"VnfPostRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"vnfIndex\":{\"type\":\"string\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"flavourId\":{\"type\":\"string\"},\"pnfInfo\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"extNSVirtualLink\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nestedNsInstanceId\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"jobId\":{\"type\":\"string\"},\"locationConstraints\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"}}},\"DeleteVlResponse\":{\"type\":\"object\",\"properties\":{\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"vlInfo\":{\"type\":\"object\",\"properties\":{\"vldId\":{\"type\":\"string\"},\"vlInstanceName\":{\"type\":\"string\"},\"vlInstanceId\":{\"type\":\"string\"},\"relatedCpInstanceId\":{\"items\":{\"$ref\":\"#/definitions/cpInfo\"},\"type\":\"array\"}}},\"cpInfo\":{\"type\":\"object\",\"properties\":{\"cpInstanceId\":{\"type\":\"string\"},\"cpdId\":{\"type\":\"string\"},\"cpInstanceName\":{\"type\":\"string\"}}},\"SfcPostResponse\":{\"type\":\"object\",\"properties\":{\"sfcInstId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"}}},\"NsInstantiateRequest\":{\"type\":\"object\",\"properties\":{\"additionalParamForNs\":{\"type\":\"string\"},\"LocationConstraints\":{\"items\":{\"$ref\":\"#/definitions/LocationConstraint\"},\"type\":\"array\"}}},\"JobInfo\":{\"type\":\"object\",\"properties\":{\"jobId\":{\"type\":\"string\"}}},\"NsInstancesInfo\":{\"items\":{\"$ref\":\"#/definitions/NsInstanceInfo\"},\"type\":\"array\"},\"NsScaleByStepsData\":{\"type\":\"object\",\"properties\":{\"numberOfSteps\":{\"type\":\"integer\"},\"scalingDirection\":{\"type\":\"string\"},\"aspectId\":{\"type\":\"string\"}}},\"vnffgInfo\":{\"type\":\"object\",\"properties\":{\"cpId\":{\"type\":\"string\"},\"virtualLinkId\":{\"type\":\"string\"},\"vnfId\":{\"type\":\"string\"},\"pnfId\":{\"type\":\"string\"},\"nfp\":{\"type\":\"string\"},\"vnffgInstanceId\":{\"type\":\"string\"}}},\"TableInfo\":{\"type\":\"object\",\"properties\":{\"count\":{\"type\":\"string\"}}}},\"swagger\":\"2.0\",\"consumes\":[\"application/json\"]}","definition":""}]}};
+export const workflowFJH = {"id":"fjh","name":"fjh","nodes":[{"id":"node0","name":"startEvent","type":"startEvent","position":{"top":31,"left":31,"width":200,"height":100},"connection":[{"sourceRef":"node0","targetRef":"node23"}],"parameters":[{"name":"vlCount","value":"","valueSource":"String","type":"String"},{"name":"vnfCount","value":"","valueSource":"String","type":"String"},{"name":"sfcCount","value":"","valueSource":"String","type":"String"},{"name":"object_context","value":"","valueSource":"String","type":"String"},{"name":"nsInstanceId","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForNs","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForVnf","value":"","valueSource":"String","type":"String"},{"name":"jobId","value":"","valueSource":"String","type":"String"},{"name":"sdnControllerId","value":"","valueSource":"String","type":"String"},{"name":"templateid","value":"","valueSource":"String","type":"String"},{"name":"instanceid","value":"","valueSource":"String","type":"String"},{"name":"sdnolcmurl","value":"","valueSource":"String","type":"String"},{"name":"statusurl","value":"","valueSource":"String","type":"String"}]},{"id":"node1","name":"endEvent","type":"endEvent","position":{"top":668,"left":955,"width":200,"height":100},"connection":[]},{"id":"node2","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":120,"left":169,"width":200,"height":100},"connection":[{"sourceRef":"node2","targetRef":"node3","condition":"${ vl_index <= vlCount and vl_status='active' }","name":"未完成"},{"sourceRef":"node2","targetRef":"node4","condition":"!( vl_index <= vlCount and vl_status='active' )","name":"创建完成"}]},{"id":"node3","name":"createVL","type":"restTask","position":{"top":213,"left":142,"width":200,"height":100},"connection":[{"sourceRef":"node3","targetRef":"node11"}],"produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"body","valueSource":"String","type":"String","position":"body","schema":{"$ref":"#/definitions/VlPostRequest"}}],"responses":[{"description":"","schema":{"$ref":"#/definitions/VlPostResponse"}}],"restConfigId":"nslcm","path":"/ns/vls","method":"post"},{"id":"node4","name":"restTask","type":"restTask","position":{"top":115,"left":358,"width":200,"height":100},"connection":[{"sourceRef":"node4","targetRef":"node5"}],"produces":[],"consumes":[],"parameters":[],"responses":[],"restConfigId":"nslcm","path":"","method":""},{"id":"node5","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":212,"left":383,"width":200,"height":100},"connection":[{"sourceRef":"node5","targetRef":"node6","condition":"未完成"},{"sourceRef":"node5","targetRef":"node12","condition":"创建完成"}]},{"id":"node6","name":"createVNF","type":"restTask","position":{"top":306,"left":352,"width":200,"height":100},"connection":[{"sourceRef":"node6","targetRef":"node7"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node7","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":558,"left":443,"width":200,"height":100},"connection":[{"sourceRef":"node7","targetRef":"node8"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node8","name":"query_vnf nslcm","type":"restTask","position":{"top":639,"left":216,"width":200,"height":100},"connection":[{"sourceRef":"node8","targetRef":"node9"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node9","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":539,"left":264,"width":200,"height":100},"connection":[{"sourceRef":"node9","targetRef":"node7","condition":"未完成"},{"sourceRef":"node9","targetRef":"node10","condition":"已完成"}]},{"id":"node10","name":"scriptTask","type":"scriptTask","position":{"top":303,"left":239,"width":200,"height":100},"connection":[{"sourceRef":"node10","targetRef":"node5"}]},{"id":"node11","name":"scriptTask","type":"scriptTask","position":{"top":207,"left":34,"width":200,"height":100},"connection":[{"sourceRef":"node11","targetRef":"node2"}]},{"id":"node12","name":"restTask","type":"restTask","position":{"top":205,"left":732,"width":200,"height":100},"connection":[{"sourceRef":"node12","targetRef":"node13"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node13","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":287,"left":757,"width":200,"height":100},"connection":[{"sourceRef":"node13","targetRef":"node14","condition":"未结束"},{"sourceRef":"node13","targetRef":"node18","condition":"已结束"}]},{"id":"node14","name":"createSfc","type":"restTask","position":{"top":440,"left":726,"width":200,"height":100},"connection":[{"sourceRef":"node14","targetRef":"node15"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node15","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":551,"left":754,"width":200,"height":100},"connection":[{"sourceRef":"node15","targetRef":"node16"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node16","name":"restTask","type":"restTask","position":{"top":642,"left":589,"width":200,"height":100},"connection":[{"sourceRef":"node16","targetRef":"node17"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node17","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":551,"left":614,"width":200,"height":100},"connection":[{"sourceRef":"node17","targetRef":"node15","condition":"未结束"},{"sourceRef":"node17","targetRef":"node19","condition":"已结束"}]},{"id":"node18","name":"restTask","type":"restTask","position":{"top":282,"left":927,"width":200,"height":100},"connection":[{"sourceRef":"node18","targetRef":"node20"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node19","name":"scriptTask","type":"scriptTask","position":{"top":275,"left":588,"width":200,"height":100},"connection":[{"sourceRef":"node19","targetRef":"node13"}]},{"id":"node20","name":"Assign_all_status","type":"scriptTask","position":{"top":380,"left":928,"width":200,"height":100},"connection":[{"sourceRef":"node20","targetRef":"node21"}]},{"id":"node21","name":"post_do","type":"restTask","position":{"top":497,"left":929,"width":200,"height":100},"connection":[{"sourceRef":"node21","targetRef":"node22"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node22","name":"jobstatus","type":"restTask","position":{"top":586,"left":927,"width":200,"height":100},"connection":[{"sourceRef":"node22","targetRef":"node1"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node23","name":"scriptTask","type":"scriptTask","position":{"top":16,"left":143,"width":200,"height":100},"connection":[{"sourceRef":"node23","targetRef":"node2"}],"scriptFormate":"javascript","script":"execution.setVariable(\"vl_index\", 1);\nexecution.setVariable(\"vl_status\", \"active\");"}],"configs":{"microservices":[{"name":"nslcm","version":"v1","swaggerJson":"{\"info\":{\"version\":\"1.0.0\",\"contact\":{\"url\":\"https://gerrit.onap.org/r/#/admin/projects/vfc/nfvo/lcm\",\"name\":\"ONAP VFC team\",\"email\":\"onap-discuss@lists.onap.org\"},\"description\":\"VFC Network Service Lifecycle Management Rest API.\",\"title\":\"ONAP VFC Network Service Lifecycle Management API\"},\"paths\":{\"/ns/sfcs/{sfcInstId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteResponse\"}},\"404\":{\"description\":\"the sfc instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"sfcInstId\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"delete sfc\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_sfc\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/SfcInfo\"}},\"404\":{\"description\":\"the sfc instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"sfc instance id\",\"required\":true,\"type\":\"string\",\"name\":\"sfcInstId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"query the specified sfc info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_sfc\"}},\"/ns/{nsInstanceId}/postdeal\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NSInstPostDetailRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"postdeal\"],\"summary\":\"ns postdeal\",\"consumes\":[\"application/json\"],\"operationId\":\"ns_postdeal\"}},\"/ns/vnfs\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/VnfPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/VnfPostRequest\"},\"description\":\"instantiate request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"vnf create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_vnf\"}},\"/ns/{ns_instance_id}/heal\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"},{\"schema\":{\"$ref\":\"#/definitions/NsHealRequest\"},\"description\":\"healVnfData\",\"required\":true,\"name\":\"healVnfData\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns heal\",\"summary\":\"ns heal\",\"operationId\":\"ns_heal\"}},\"/jobs/{jobId}\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"jobId\"},{\"schema\":{\"$ref\":\"#/definitions/JobProgressRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"tags\":[\"job\"],\"description\":\"\",\"summary\":\"jobstatus\",\"operationId\":\"post_jobprogress\"},\"get\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobDetailInfo\"}}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"job Id\",\"in\":\"path\",\"name\":\"jobId\"},{\"required\":true,\"type\":\"string\",\"description\":\"job response message id\",\"in\":\"query\",\"name\":\"responseId\"}],\"tags\":[\"job\"],\"description\":\"\",\"summary\":\"jobstatus\",\"operationId\":\"get_jobstatus\"}},\"/ns/vls/{vlId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteVlResponse\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"vlId\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"delete vl\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_vl\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/VlInfo\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"vl instance id\",\"required\":true,\"type\":\"string\",\"name\":\"vlId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"query the specified vl info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_vl\"}},\"/ns/vls\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/VlPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/VlPostRequest\"},\"description\":\"instantiate request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"vl create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_vl\"}},\"/ns/sfcs\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/SfcPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/SfcPostRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"sfc create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_sfc\"}},\"/ns/{ns_instance_id}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"The NS instance resource and the associated NS identifier were deleted successfully.\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"}],\"tags\":[\"ns\"],\"description\":\"ns delete\",\"summary\":\"ns delete\",\"operationId\":\"ns_delete\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsInstanceInfo\"}}},\"parameters\":[],\"tags\":[\"ns\"],\"description\":\"ns get\",\"summary\":\"ns get\",\"operationId\":\"ns_instance_get\"}},\"/ns/vnfs/{vnfInstId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteResponse\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"vnfInstId\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"delete vnf\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_vnf\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/VnfInfo\"}},\"404\":{\"description\":\"the vnf instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"vnf instance id\",\"required\":true,\"type\":\"string\",\"name\":\"vnfInstId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"query the specified vnf info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_vnf\"}},\"/ns\":{\"post\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsCreateResponse\"}}},\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/NsCreateRequest\"},\"description\":\"NS Instance Create Request\",\"required\":true,\"name\":\"NSCreateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns create\",\"summary\":\"ns create\",\"operationId\":\"ns_create\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsInstancesInfo\"}}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"job response message id\",\"in\":\"query\",\"name\":\"csarId\"}],\"tags\":[\"ns\"],\"description\":\"ns get\",\"summary\":\"ns get\",\"operationId\":\"ns_instantces_get\"}},\"/ns/{ns_instance_id}/terminate\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"},{\"schema\":{\"$ref\":\"#/definitions/NsTerminateRequest\"},\"description\":\"NsTerminateRequest\",\"required\":true,\"name\":\"NsTerminateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns terminate\",\"summary\":\"ns terminate\",\"operationId\":\"ns_terminate\"}},\"/ns/{nsInstanceId}/scale\":{\"post\":{\"responses\":{\"200\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"201\":{\"description\":\"Invalid Request\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NsScaleRequest\"},\"description\":\"Scale NS Request Body\",\"required\":true,\"name\":\"ScaleNSRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns scale\",\"summary\":\"ns scale\",\"operationId\":\"ns_scale\"}},\"/mandb/{modelName}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"The tables were deleted successfully.\"}},\"description\":\"ns table delete\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"model Name.\",\"in\":\"path\",\"name\":\"modelName\"}],\"produces\":[\"application/json\"],\"tags\":[\"db\"],\"summary\":\"ns table delete\",\"consumes\":[\"application/json\"],\"operationId\":\"ns_table_delete\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/TableInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"query ns table info\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"model Name.\",\"in\":\"path\",\"name\":\"modelName\"}],\"produces\":[\"application/json\"],\"tags\":[\"db\"],\"summary\":\"query ns table info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_ns_table\"}},\"/ns/{nsInstanceId}/Instantiate\":{\"post\":{\"responses\":{\"200\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"201\":{\"description\":\"Invalid Request\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NsInstantiateRequest\"},\"description\":\"NS Instantiate Request Body\",\"required\":true,\"name\":\"NSInstantiateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns Instantiate\",\"summary\":\"ns Instantiate\",\"operationId\":\"ns_Instantiate\"}}},\"schemes\":[\"http\",\"https\"],\"produces\":[\"application/json\"],\"basePath\":\"/api/nslcm/v1\",\"definitions\":{\"NsInstanceInfo\":{\"type\":\"object\",\"properties\":{\"nsState\":{\"type\":\"string\"},\"vnfInfo\":{\"items\":{\"$ref\":\"#/definitions/vnfInfo\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"nsdId\":{\"type\":\"string\"},\"vlInfo\":{\"items\":{\"$ref\":\"#/definitions/vlInfo\"},\"type\":\"array\"},\"nsName\":{\"type\":\"string\"},\"vnffgInfo\":{\"items\":{\"$ref\":\"#/definitions/vnffgInfo\"},\"type\":\"array\"},\"description\":{\"type\":\"string\"}}},\"JobDetailInfo\":{\"type\":\"object\",\"properties\":{\"responseDescriptor\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"},\"responseHistoryList\":{\"items\":{\"$ref\":\"#/definitions/jobResponseInfo\"},\"type\":\"array\"},\"responseId\":{\"type\":\"string\"},\"errorCode\":{\"type\":\"string\"},\"progress\":{\"type\":\"string\"},\"statusDescription\":{\"type\":\"string\"}}},\"jobId\":{\"type\":\"string\"}}},\"VnfInfo\":{\"type\":\"object\",\"properties\":{\"vnfInstId\":{\"type\":\"string\"},\"vnfName\":{\"type\":\"string\"},\"vnfStatus\":{\"type\":\"string\"}}},\"DeleteResponse\":{\"type\":\"object\",\"properties\":{\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"NsHealRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceId\":{\"type\":\"string\"},\"cause\":{\"type\":\"string\"},\"additionalParams\":{\"type\":\"object\",\"properties\":{\"action\":{\"type\":\"string\"},\"actionvminfo\":{\"type\":\"object\",\"properties\":{\"vmname\":{\"type\":\"string\"},\"vmid\":{\"type\":\"string\"}}}}}}},\"NsScaleRequest\":{\"type\":\"object\",\"properties\":{\"scaleNsByStepsData\":{\"$ref\":\"#/definitions/NsScaleByStepsData\"},\"scaleType\":{\"type\":\"string\"}}},\"jobResponseInfo\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"},\"progress\":{\"type\":\"string\"},\"responseId\":{\"type\":\"string\"},\"statusDescription\":{\"type\":\"string\"},\"errorCode\":{\"type\":\"string\"}}},\"NSInstPostDetailRequest\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"}}},\"VlInfo\":{\"type\":\"object\",\"properties\":{\"vlId\":{\"type\":\"string\"},\"vlStatus\":{\"type\":\"string\"},\"vlName\":{\"type\":\"string\"}}},\"VnfPostResponse\":{\"type\":\"object\",\"properties\":{\"vnfInstId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"}}},\"NsCreateRequest\":{\"type\":\"object\",\"properties\":{\"nsName\":{\"type\":\"string\"},\"csarId\":{\"type\":\"string\",\"description\":\"the NS package ID\"},\"description\":{\"type\":\"string\"}}},\"VlPostResponse\":{\"type\":\"object\",\"properties\":{\"vlId\":{\"type\":\"string\"},\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"SfcPostRequest\":{\"type\":\"object\",\"properties\":{\"sdnControllerId\":{\"type\":\"string\"},\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"fpindex\":{\"type\":\"string\"}}},\"NsTerminateRequest\":{\"type\":\"object\",\"properties\":{\"gracefulTerminationTimeout\":{\"type\":\"string\"},\"terminationType\":{\"type\":\"string\"}}},\"JobProgressRequest\":{\"type\":\"object\",\"properties\":{\"progress\":{\"type\":\"string\"},\"errcode\":{\"type\":\"string\"},\"desc\":{\"type\":\"string\"}}},\"SfcInfo\":{\"type\":\"object\",\"properties\":{\"sfcName\":{\"type\":\"string\"},\"sfcInstId\":{\"type\":\"string\"},\"sfcStatus\":{\"type\":\"string\"}}},\"vnfInfo\":{\"type\":\"object\",\"properties\":{\"vnfInstanceId\":{\"type\":\"string\"},\"vnfdId\":{\"type\":\"string\"},\"vnfInstanceName\":{\"type\":\"string\"}}},\"LocationConstraint\":{\"type\":\"object\",\"properties\":{\"locationConstraints\":{\"type\":\"object\",\"properties\":{\"vimid\":{\"type\":\"string\"}}},\"vnfProfileId\":{\"type\":\"string\"}}},\"NsCreateResponse\":{\"type\":\"object\",\"properties\":{\"nsInstanceId\":{\"type\":\"string\"}}},\"VlPostRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"flavourId\":{\"type\":\"string\"},\"pnfInfo\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"extNSVirtualLink\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nestedNsInstanceId\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"jobId\":{\"type\":\"string\"},\"locationConstraints\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"vlIndex\":{\"type\":\"string\"}}},\"VnfPostRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"vnfIndex\":{\"type\":\"string\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"flavourId\":{\"type\":\"string\"},\"pnfInfo\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"extNSVirtualLink\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nestedNsInstanceId\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"jobId\":{\"type\":\"string\"},\"locationConstraints\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"}}},\"DeleteVlResponse\":{\"type\":\"object\",\"properties\":{\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"vlInfo\":{\"type\":\"object\",\"properties\":{\"vldId\":{\"type\":\"string\"},\"vlInstanceName\":{\"type\":\"string\"},\"vlInstanceId\":{\"type\":\"string\"},\"relatedCpInstanceId\":{\"items\":{\"$ref\":\"#/definitions/cpInfo\"},\"type\":\"array\"}}},\"cpInfo\":{\"type\":\"object\",\"properties\":{\"cpInstanceId\":{\"type\":\"string\"},\"cpdId\":{\"type\":\"string\"},\"cpInstanceName\":{\"type\":\"string\"}}},\"SfcPostResponse\":{\"type\":\"object\",\"properties\":{\"sfcInstId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"}}},\"NsInstantiateRequest\":{\"type\":\"object\",\"properties\":{\"additionalParamForNs\":{\"type\":\"string\"},\"LocationConstraints\":{\"items\":{\"$ref\":\"#/definitions/LocationConstraint\"},\"type\":\"array\"}}},\"JobInfo\":{\"type\":\"object\",\"properties\":{\"jobId\":{\"type\":\"string\"}}},\"NsInstancesInfo\":{\"items\":{\"$ref\":\"#/definitions/NsInstanceInfo\"},\"type\":\"array\"},\"NsScaleByStepsData\":{\"type\":\"object\",\"properties\":{\"numberOfSteps\":{\"type\":\"integer\"},\"scalingDirection\":{\"type\":\"string\"},\"aspectId\":{\"type\":\"string\"}}},\"vnffgInfo\":{\"type\":\"object\",\"properties\":{\"cpId\":{\"type\":\"string\"},\"virtualLinkId\":{\"type\":\"string\"},\"vnfId\":{\"type\":\"string\"},\"pnfId\":{\"type\":\"string\"},\"nfp\":{\"type\":\"string\"},\"vnffgInstanceId\":{\"type\":\"string\"}}},\"TableInfo\":{\"type\":\"object\",\"properties\":{\"count\":{\"type\":\"string\"}}}},\"swagger\":\"2.0\",\"consumes\":[\"application/json\"]}","definition":""}]}};
diff --git a/sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts b/sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts
index f0013bc5..c6cf60a8 100644
--- a/sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts
+++ b/sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts
@@ -12,10 +12,13 @@
import { Injectable } from '@angular/core';
import * as jsp from 'jsplumb';
-import { ModelService } from "./model.service";
-import { BroadcastService } from "./broadcast.service";
+
import { Subscription } from 'rxjs/Subscription';
-import { WorkflowNode } from "../model/workflow/workflow-node";
+import { WorkflowNode } from '../model/workflow/workflow-node';
+import { BroadcastService } from './broadcast.service';
+import { ModelService } from './model.service';
+import { SequenceFlow } from '../model/workflow/sequence-flow';
+import { Position } from '../model/workflow/position';
/**
* JsPlumbService
@@ -23,68 +26,120 @@ import { WorkflowNode } from "../model/workflow/workflow-node";
*/
@Injectable()
export class JsPlumbService {
- public jsplumbInstance;
+ public jsplumbInstanceMap = new Map<string, any>();
public subscriptionMap = new Map<string, Subscription>();
- constructor(private processService: ModelService, private broadcastService: BroadcastService) {
- this.jsplumbInstance = jsp.jsPlumb.getInstance({
- Container: 'canvas'
+ private padding = 20;
+ private rootClass = 'canvas';
+ private selectNodes: WorkflowNode[] = [];
+
+ constructor(private modelService: ModelService, private broadcastService: BroadcastService) {
+ this.broadcastService.selectedElement$.subscribe(elements => {
+ this.selectNodes = [];
+ if (elements && 0 < elements.length) {
+ for (let index = 0; index < elements.length; index++) {
+ let element = elements[index];
+ if (this.modelService.isNode(element)) {
+ let node = element as WorkflowNode;
+ this.selectNodes.push(node);
+ }
+ }
+ }
});
- this.initJsPlumbInstance();
- this.broadcastService.workflow.subscribe(Workflow => {
- this.jsplumbInstance.reset();
- this.unsubscriptionAll();
- this.initJsPlumbInstance();
- this.buttonDraggable();
- this.buttonDroppable();
+ }
+
+ public connectChildrenNodes(parentNodeId: string) {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(parentNodeId);
+
+ const nodes: WorkflowNode[] = this.modelService.getChildrenNodes(parentNodeId);
+ nodes.forEach(node => this.connect4OneNode(node, jsplumbInstance));
+ }
+
+ public connect4OneNode(node: WorkflowNode, jsplumbInstance: any) {
+ node.connection.forEach(sequenceFlow => {
+ const connection = jsplumbInstance.connect({
+ source: sequenceFlow.sourceRef,
+ target: sequenceFlow.targetRef,
+ });
+ if (sequenceFlow.name) {
+ connection.setLabel(sequenceFlow.name);
+ }
});
}
+ public initJsPlumbInstance(id: string) {
+ if (this.jsplumbInstanceMap.get(id)) {
+ return;
+ }
+ const jsplumbInstance = jsp.jsPlumb.getInstance();
- public initJsPlumbInstance() {
- this.jsplumbInstance.importDefaults({
- Anchor: ['Top', 'RightMiddle', 'LeftMiddle', 'Bottom'],
- Connector: [
- 'Flowchart',
- { cornerRadius: 0, stub: 0, gap: 3 },
- ],
- ConnectionOverlays: [
- [
- 'Arrow',
- { direction: 1, foldback: 1, location: 1, width: 10, length: 10 },
- ],
- ['Label', { label: '', id: 'label', cssClass: 'aLabel' }],
- ],
- Endpoint: 'Blank',
+ jsplumbInstance.importDefaults({
+ Anchor: "Continuous",
+ Endpoint: "Blank",
+ Container: "pallete",
+ ReattachConnections: true,
+ Connector: ['Flowchart', {
+ stub: [0, 0],
+ cornerRadius: 5,
+ alwaysRespectStubs: true
+ }],
PaintStyle: {
- strokeWidth: 4,
- stroke: 'black',
+ stroke: "#7D8695",
+ strokeWidth: 1,
+ radius: 1,
+ outlineStroke: "transform",
+ outlineWidth: 4
},
- HoverPaintStyle: {
- strokeWidth: 4,
- stroke: 'blue',
+ ConnectorStyle: {
+ stroke: "#7D8695",
+ strokeWidth: 1,
+ outlineStroke: "transform",
+ outlineWidth: 4
},
+ ConnectorHoverStyle: {
+ stroke: "#00ABFF",
+ strokeWidth: 2,
+ outlineStroke: "transform",
+ outlineWidth: 4
+ },
+ ConnectionOverlays: [
+ ['Arrow', {
+ location: 1,
+ id: 'arrow',
+ cssClass: 'icon-port',
+ width: 11,
+ length: 12
+ }],
+ ['Label', { label: '', id: 'label' }]
+ ]
});
// add connection to model data while a new connection is build
- this.jsplumbInstance.bind('connection', info => {
- this.processService.addSequenceFlow(info.connection.sourceId, info.connection.targetId);
+ jsplumbInstance.bind('connection', info => {
+ this.modelService.addConnection(info.connection.sourceId, info.connection.targetId);
this.subscribe4Connection(info.connection);
- info.connection.bind('click', connection => {
- const sequenceFlow = this.processService.getSequenceFlow(connection.sourceId, connection.targetId);
- this.broadcastService.broadcast(this.broadcastService.currentSequenceFlow, sequenceFlow);
- this.broadcastService.broadcast(this.broadcastService.currentType, 'SequenceFlow');
+ info.connection.bind('click', (connection, event) => {
+ if ('Label' === connection.type) {
+ return;
+ }
+ event.stopPropagation();
+ const sequenceFlow = this.modelService.getSequenceFlow(connection.sourceId, connection.targetId);
+ this.broadcastService.broadcast(this.broadcastService.showProperty, null);
+ this.broadcastService.broadcast(this.broadcastService.selectedElement, [sequenceFlow]);
});
info.connection.bind('dblclick', connection => {
- const sequenceFlow = this.processService.getSequenceFlow(connection.sourceId, connection.targetId);
- this.broadcastService.broadcast(this.broadcastService.sequenceFlow, sequenceFlow);
- this.broadcastService.broadcast(this.broadcastService.showSequenceFlow, true);
+ if ('Label' === connection.type) {
+ return;
+ }
+ const sequenceFlow = this.modelService.getSequenceFlow(connection.sourceId, connection.targetId);
+ this.broadcastService.broadcast(this.broadcastService.showProperty, sequenceFlow);
});
});
+ this.jsplumbInstanceMap.set(id, jsplumbInstance);
}
private subscribe4Connection(connection: any) {
@@ -94,128 +149,414 @@ export class JsPlumbService {
sequenceFlowSubscription.unsubscribe();
}
- sequenceFlowSubscription = this.broadcastService.currentSequenceFlow$.subscribe(currentSequenceFlow => {
- if (currentSequenceFlow.sourceRef === connection.sourceId
- && currentSequenceFlow.targetRef === connection.targetId) {
- connection.setPaintStyle({ stroke: 'red' });
+ let currentThis = this;
+ sequenceFlowSubscription = this.broadcastService.selectedElement$.subscribe(elements => {
+ let selected = false;
+ if (elements && 0 < elements.length) {
+ for (let index = 0; index < elements.length; index++) {
+ let element = elements[index];
+ if (!this.modelService.isNode(element)) {
+ let sequence = element as SequenceFlow;
+ if (sequence.sourceRef === connection.sourceId
+ && sequence.targetRef === connection.targetId) {
+ selected = true;
+ }
+ }
+ }
+ }
+ if (selected) {
+ connection.setPaintStyle({
+ stroke: '#00ABFF',
+ strokeWidth: 1,
+ radius: 1,
+ outlineStroke: "transform",
+ outlineWidth: 4
+ });
} else {
- connection.setPaintStyle({ stroke: 'black' });
+ connection.setPaintStyle({
+ stroke: '#7D8695',
+ strokeWidth: 1,
+ radius: 1,
+ outlineStroke: "transform",
+ outlineWidth: 4
+ });
}
});
-
this.subscriptionMap.set(pre + 'sequenceFlowSubscription', sequenceFlowSubscription);
-
- let typeSubscription = this.subscriptionMap.get(pre + 'typeSubscription');
- if (typeSubscription && !typeSubscription.closed) {
- typeSubscription.unsubscribe();
- }
- typeSubscription = this.broadcastService.currentType$.subscribe(type => {
- if (type === 'WorkflowNode') {
- connection.setPaintStyle({ stroke: 'black' });
- }
- });
- this.subscriptionMap.set(pre + 'typeSubscription', typeSubscription);
}
private unsubscription4Connection(connectionSelection: any) {
connectionSelection.each(connection => {
const pre = connection.sourceId + connection.targetId;
this.subscriptionMap.get(pre + 'sequenceFlowSubscription').unsubscribe();
- this.subscriptionMap.get(pre + 'typeSubscription').unsubscribe();
});
}
- private unsubscriptionAll() {
- this.subscriptionMap.forEach(subscription => subscription.unsubscribe());
+ public deleteConnect(sourceId: string, targetId: string) {
+ const sourceNode = this.modelService.getNodeMap().get(sourceId);
+ const jsplumbInstance = this.jsplumbInstanceMap.get(sourceNode.parentId);
+ const connectionSelection = jsplumbInstance.select({ source: sourceId, target: targetId });
+ this.unsubscription4Connection(connectionSelection);
+ connectionSelection.delete();
+ }
+
+ public setLabel(sourceId: string, targetId: string, label: string) {
+ const sourceNode = this.modelService.getNodeMap().get(sourceId);
+ const jsplumbInstance = this.jsplumbInstanceMap.get(sourceNode.parentId);
+ const connections = jsplumbInstance.select({ source: sourceId, target: targetId });
+ connections.setLabel(label);
}
- public initNode() {
- this.processService.getProcess().forEach(node => {
- this.jsplumbInstance.draggable(node.id, {
- stop: event => {
- node.position.left = event.pos[0];
- node.position.top = event.pos[1];
- },
- });
+ public getParentNodeId(id: string): string {
+ const nodeElement = jsp.jsPlumb.getSelector('#' + id);
+ const parentNode = this.getParentNodeEl(nodeElement[0]);
- this.jsplumbInstance.makeTarget(node.id, {
- detachable: false,
- isTarget: true,
- maxConnections: -1,
- });
+ return parentNode ? parentNode.id : null;
+ }
- this.jsplumbInstance.makeSource(node.id, {
- filter: '.anchor, .anchor *',
- detachable: false,
- isSource: true,
- maxConnections: -1,
- });
+ public initNode(node: WorkflowNode) {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);
+
+ this.jsplumbInstanceMap.get(this.modelService.rootNodeId).draggable(node.id, {
+ scope: 'node',
+ filter: '.ui-resizable-handle',
+ classes: {
+ 'ui-draggable': 'dragging'
+ },
+ // grid: [5, 5],
+ drag: event => {
+ // out of container edge, reset to minimal value.
+ if (0 > event.pos[0]) {
+ event.el.style.left = '0px';
+ }
+ if (0 > event.pos[1]) {
+ event.el.style.top = '0px';
+ }
+
+ if (0 < this.selectNodes.length) {
+ let moveAll = false;
+ this.selectNodes.forEach(element => {
+ if (element.id === event.el.id) {
+ moveAll = true;
+ }
+ });
+ if (moveAll) {
+ this.selectNodes.forEach(selectNode => {
+ if (selectNode.id !== event.el.id) {
+ selectNode.position.left += event.e.movementX;
+ selectNode.position.left = 0 > selectNode.position.left ? 0 : selectNode.position.left;
+ selectNode.position.top += event.e.movementY;
+ selectNode.position.top = 0 > selectNode.position.top ? 0 : selectNode.position.top;
+ }
+ jsplumbInstance.revalidate(jsplumbInstance.getSelector('#' + selectNode.id));
+ });
+ }
+ }
+ },
+ stop: event => {
+ this.selectNodes.forEach(selectNode => {
+ jsplumbInstance.revalidate(jsplumbInstance.getSelector('#' + selectNode.id));
+ });
+ }
+ });
+
+ jsplumbInstance.makeTarget(node.id, {
+ maxConnections: -1,
+ beforeDrop: function (info) {
+ const sourceId = info.sourceId;
+ const targetId = info.targetId;
+ if (sourceId === targetId) {
+ return false;
+ }
+ const sameConnections = this.instance.getConnections({ source: sourceId, target: targetId });
+ if (sameConnections && 0 < sameConnections.length) {
+ return false;
+ }
+ return true;
+ }
+
+ });
+
+ jsplumbInstance.makeSource(node.id, {
+ filter: '.anchor, .anchor *',
+ maxConnections: -1,
});
}
- public connectNodes() {
- const nodes: WorkflowNode[] = this.processService.getProcess();
- nodes.forEach(node => this.connect4OneNode(node));
+ public nodeDroppable(node: WorkflowNode, rank: number) {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);
+
+ const selector = jsplumbInstance.getSelector('#' + node.id);
+ this.jsplumbInstanceMap.get(this.modelService.rootNodeId).droppable(selector, {
+ scope: 'node',
+ rank,
+ tolerance: 'pointer',
+ drop: event => {
+ if (!this.isChildNode(event.drop.el, event.drag.el)) {
+ this.drop(event);
+ }
+ return true;
+ },
+ canDrop: drag => {
+ const nodeMap = this.modelService.getNodeMap();
+ const ancestorNode = nodeMap.get(drag.el.id);
+
+ const isAncestor = this.modelService.isDescendantNode(ancestorNode, node.id);
+ return !isAncestor;
+ },
+ });
}
- public connect4OneNode(node: WorkflowNode) {
- node.sequenceFlows.forEach(sequenceFlow => {
- const connection = this.jsplumbInstance.connect({
- source: sequenceFlow.sourceRef,
- target: sequenceFlow.targetRef,
- });
- if (sequenceFlow.name) {
- connection.setLabel(sequenceFlow.name);
+ private isChildNode(childElement, parentElement) {
+ while (childElement !== parentElement) {
+ childElement = childElement.parentNode;
+ if (childElement.classList.contains('canvas')) {
+ return false;
}
- });
+ }
+
+ return true;
}
- public setLabel(sourceId: string, targetId: string, label: string) {
- const sourceNode = this.processService.getNodeById(sourceId);
- const connections = this.jsplumbInstance.select({ source: sourceId, target: targetId });
- connections.setLabel(label);
+ private drop(event) {
+ const dragEl = event.drag.el;
+ const dropEl = event.drop.el;
+
+ this.resizeParent(dragEl, dropEl);
+
+ const nodeLeft = dragEl.getBoundingClientRect().left;
+ const nodeTop = dragEl.getBoundingClientRect().top;
+ const parentLeft = dropEl.getBoundingClientRect().left;
+ const parentTop = dropEl.getBoundingClientRect().top;
+ const left = nodeLeft - parentLeft + dropEl.scrollLeft;
+ const top = nodeTop - parentTop + dropEl.scrollTop;
+ dragEl.style.top = top + 'px';
+ dragEl.style.left = left + 'px';
+
+ // 12 is title height
+ this.modelService.updatePosition(dragEl.id, left, top, dragEl.getBoundingClientRect().width, dragEl.getBoundingClientRect().height - 12);
+
+ const originalParentNode = this.getParentNodeEl(dragEl);
+ const originalParentNodeId = originalParentNode ? originalParentNode.id : this.modelService.rootNodeId;
+
+ const targetParentNodeId = dropEl.classList.contains('node') ? dropEl.id : this.modelService.rootNodeId;
+ this.changeParent(dragEl.id, originalParentNodeId, targetParentNodeId);
}
- public deleteConnect(sourceId: string, targetId: string) {
- const sourceNode = this.processService.getNodeById(sourceId);
- const connectionSelection = this.jsplumbInstance.select({ source: sourceId, target: targetId });
- this.unsubscription4Connection(connectionSelection);
- connectionSelection.delete();
+ private changeParent(id: string, originalParentNodeId: string, targetParentNodeId: string) {
+ if (originalParentNodeId !== targetParentNodeId) {
+ this.jsplumbInstanceMap.get(originalParentNodeId).removeAllEndpoints(id);
+ this.modelService.changeParent(id, originalParentNodeId, targetParentNodeId);
+ }
}
- public remove(nodeId: string) {
- // unsubscription4Connection
- const connectionsAsSource = this.jsplumbInstance.select({ source: nodeId });
- this.unsubscription4Connection(connectionsAsSource);
- const connectionsAsTarget = this.jsplumbInstance.select({ target: nodeId });
- this.unsubscription4Connection(connectionsAsTarget);
+ private getParentNodeEl(element) {
+ while (!(element.parentNode.classList.contains('node') || element.parentNode.classList.contains('canvas'))) {
+ element = element.parentNode;
+ }
- this.jsplumbInstance.remove(nodeId);
+ if (element.parentNode.classList.contains('canvas')) { // top level node
+ return null;
+ } else {
+ return element.parentNode;
+ }
+ }
+
+ public canvasDroppable() {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);
+ const canvasSelector = jsplumbInstance.getSelector('.canvas');
+ jsplumbInstance.droppable(canvasSelector, {
+ scope: 'node',
+ rank: 0,
+ grid: [5, 5],
+ drop: event => this.drop(event),
+ });
}
public buttonDraggable() {
- const selector = this.jsplumbInstance.getSelector('.toolbar .item');
- this.jsplumbInstance.draggable(selector,
- {
- scope: 'btn',
- clone: true,
- });
+ const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);
+ const selector = jsplumbInstance.getSelector('.item');
+ jsplumbInstance.draggable(selector, {
+ scope: 'btn',
+ clone: true
+ });
}
public buttonDroppable() {
- const selector = this.jsplumbInstance.getSelector('.canvas');
- this.jsplumbInstance.droppable(selector, {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);
+ const selector = jsplumbInstance.getSelector('.canvas');
+ jsplumbInstance.droppable(selector, {
scope: 'btn',
+ // grid: [5, 5],
drop: event => {
- const el = this.jsplumbInstance.getSelector(event.drag.el);
+ const el = jsplumbInstance.getSelector(event.drag.el);
const type = el.attributes.nodeType.value;
- // Mouse position minus drop canvas start position and minus icon half size
- const left = event.e.clientX - 220 - (event.e.offsetX / 2);
- const top = event.e.clientY - 70 - (event.e.offsetY / 2);
-
- this.processService.addNode(type, type, top, left);
+ // Mouse position minus drop canvas start position plus scroll position.
+ let left = event.e.x - event.drop.pagePosition[0] + event.drop.el.scrollLeft;
+ let top = event.e.y - event.drop.pagePosition[1] + event.drop.el.scrollTop;
+ if (0 > left) {
+ left = 0;
+ }
+ if (0 > top) {
+ top = 0;
+ }
+ const name = event.drag.el.children[1].innerText;
+ this.modelService.addNode(name, type, left, top);
},
});
}
+ public remove(node: WorkflowNode) {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);
+
+ // unsubscription4Connection
+ const connectionsAsSource = jsplumbInstance.select({ source: node.id });
+ this.unsubscription4Connection(connectionsAsSource);
+ const connectionsAsTarget = jsplumbInstance.select({ target: node.id });
+ this.unsubscription4Connection(connectionsAsTarget);
+
+ jsplumbInstance.remove(node.id);
+ }
+
+ public resizeParent(element: any, parentElement: any) {
+ if (parentElement.classList.contains(this.rootClass)) {
+ return;
+ }
+
+ if (!parentElement.classList.contains('node')) {
+ this.resizeParent(element, parentElement.parentNode);
+ return;
+ }
+
+ const leftResized = this.resizeParentLeft(element, parentElement);
+ const rightResized = this.resizeParentRight(element, parentElement);
+ const topResized = this.resizeParentTop(element, parentElement);
+ const bottomResized = this.resizeParentBottom(element, parentElement);
+
+ if (leftResized || rightResized || topResized || bottomResized) {
+ if (parentElement.classList.contains('node')) {
+ const rect = parentElement.getBoundingClientRect();
+ this.modelService.updatePosition(parentElement.id,
+ parentElement.offsetLeft,
+ parentElement.offsetTop,
+ // title height
+ rect.width, rect.height - 12);
+ }
+ this.resizeParent(parentElement, parentElement.parentNode);
+ }
+ }
+
+ private resizeParentLeft(element: any, parentElement: any): boolean {
+ let resized = false;
+
+ const actualLeft = element.getBoundingClientRect().left;
+ const actualParentLeft = parentElement.getBoundingClientRect().left;
+
+ if (actualLeft - this.padding < actualParentLeft) {
+ const width = actualParentLeft - actualLeft + this.padding;
+
+ this.translateElement(parentElement, -width, 0, width, 0);
+ this.translateChildren(parentElement, element, width, 0);
+ resized = true;
+ }
+
+ return resized;
+ }
+
+ private resizeParentRight(element: any, parentElement: any): boolean {
+ let resized = false;
+
+ const actualLeft = element.getBoundingClientRect().left;
+ const actualRight = actualLeft + element.offsetWidth;
+
+ const actualParentLeft = parentElement.getBoundingClientRect().left;
+
+ if ((actualParentLeft + parentElement.offsetWidth) < actualRight + this.padding) {
+ this.setElementWidth(parentElement, actualRight + this.padding - actualParentLeft);
+ resized = true;
+ }
+
+ return resized;
+ }
+
+ private resizeParentBottom(element: any, parentElement: any): boolean {
+ let resized = false;
+
+ const actualTop = element.getBoundingClientRect().top;
+ const actualBottom = actualTop + element.offsetHeight;
+
+ const actualParentTop = parentElement.getBoundingClientRect().top;
+ const actualParentBottom = actualParentTop + parentElement.offsetHeight;
+
+ if (actualParentBottom < actualBottom + this.padding) {
+ this.setElementHeight(parentElement, actualBottom + this.padding - actualParentTop);
+ resized = true;
+ }
+
+ return resized;
+ }
+
+ private resizeParentTop(element: any, parentElement: any): boolean {
+ let resized = false;
+
+ const actualTop = element.getBoundingClientRect().top;
+ const actualParentTop = parentElement.getBoundingClientRect().top;
+
+ if (actualTop - this.padding < actualParentTop) {
+ const height = actualParentTop - actualTop + this.padding;
+
+ this.translateElement(parentElement, 0, -height, 0, height);
+ this.translateChildren(parentElement, element, 0, height);
+ resized = true;
+ }
+
+ return resized;
+ }
+
+ private translateElement(element, left: number, top: number, width: number, height: number) {
+ const offsetLeft = element.offsetLeft + left;
+ element.style.left = offsetLeft + 'px';
+
+ const offsetTop = element.offsetTop + top;
+ element.style.top = offsetTop + 'px';
+
+ const offsetWidth = element.offsetWidth + width;
+ element.style.width = offsetWidth + 'px';
+
+ const offsetHeight = element.offsetHeight + height;
+ element.style.height = offsetHeight + 'px';
+
+ if (element.classList.contains('node')) {
+ const node = this.modelService.getNodeMap().get(element.id);
+ this.jsplumbInstanceMap.get(node.parentId).revalidate(element.id);
+ }
+ }
+
+ private translateChildren(parentElment, excludeElement, left: number, top: number) {
+ const len = parentElment.children.length;
+ for (let i = 0; i < len; i++) {
+ const childElment = parentElment.children[i];
+ if (childElment.localName === 'b4t-node') {
+ this.translateElement(childElment.children[0], left, top, 0, 0);
+ }
+ }
+ }
+
+ private setElementHeight(element, height: number) {
+ element.style.height = height + 'px';
+ }
+
+ private setElementWidth(element, width: number) {
+ element.style.width = width + 'px';
+ }
+
+ private getActualPosition(element, offset: string) {
+ let actualPosition = element[offset];
+ let current = element.offsetParent;
+ while (current !== null) {
+ actualPosition += element[offset];
+ current = current.offsetParent;
+ }
+ return actualPosition;
+ }
}
diff --git a/sdc-workflow-designer-ui/src/app/services/model.service.ts b/sdc-workflow-designer-ui/src/app/services/model.service.ts
index 6ce49d04..65d3e490 100644
--- a/sdc-workflow-designer-ui/src/app/services/model.service.ts
+++ b/sdc-workflow-designer-ui/src/app/services/model.service.ts
@@ -18,12 +18,22 @@ import { NodeType } from "../model/workflow/node-type.enum";
import { StartEvent } from "../model/workflow/start-event";
import { SequenceFlow } from "../model/workflow/sequence-flow";
import { RestTask } from "../model/workflow/rest-task";
+import { ErrorEvent } from "../model/workflow/error-event";
import { PlanTreeviewItem } from "../model/plan-treeview-item";
import { WorkflowConfigService } from "./workflow-config.service";
import { Swagger, SwaggerModelSimple, SwaggerReferenceObject } from "../model/swagger";
import { WorkflowService } from "./workflow.service";
import { IntermediateCatchEvent } from "../model/workflow/intermediate-catch-event";
import { ScriptTask } from "../model/workflow/script-task";
+import { ToscaNodeTask } from '../model/workflow/tosca-node-task';
+import { NodeTemplate } from '../model/topology/node-template';
+import { SubProcess } from '../model/workflow/sub-process';
+import { TimerEventDefinition, TimerEventDefinitionType } from '../model/workflow/timer-event-definition';
+import { Parameter } from '../model/workflow/parameter';
+import { ValueSource } from '../model/value-source.enum';
+import { RestService } from './rest.service';
+import { BroadcastService } from './broadcast.service';
+import { RestConfig } from '../model/rest-config';
/**
* WorkflowService
@@ -31,78 +41,231 @@ import { ScriptTask } from "../model/workflow/script-task";
*/
@Injectable()
export class ModelService {
-
- constructor(private workflowService: WorkflowService, private configService: WorkflowConfigService) {
-
+ public rootNodeId = 'root';
+
+ private planModel: PlanModel = new PlanModel();
+
+ constructor(private broadcastService: BroadcastService, private restService: RestService, private workflowService: WorkflowService, private configService: WorkflowConfigService) {
+ this.broadcastService.planModel$.subscribe(plan => {
+ plan.nodes.forEach(node => {
+ switch (node.type) {
+ case NodeType[NodeType.startEvent]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.endEvent]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.restTask]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.errorStartEvent]:
+ case NodeType[NodeType.errorEndEvent]:
+ node.position.width = 26;
+ node.position.height = 26;
+ break;
+ case NodeType[NodeType.toscaNodeManagementTask]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.subProcess]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.intermediateCatchEvent]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.scriptTask]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.exclusiveGateway]:
+ case NodeType[NodeType.parallelGateway]:
+ node.position.width = 26;
+ node.position.height = 26;
+ break;
+ default:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ }
+ });
+ this.planModel = plan;
+ });
+ this.broadcastService.updateModelRestConfig$.subscribe(restConfigs => {
+ this.updateRestConfig(restConfigs);
+ });
}
public getProcess(): WorkflowNode[] {
return this.workflowService.planModel.nodes;
}
- public addNode(name: string, type: string, top: number, left: number): WorkflowNode {
- let node: WorkflowNode;
- switch (type) {
- case NodeType[NodeType.startEvent]:
- node = new StartEvent(this.createId(), name, type, new Position(top, left), []);
- break;
- case NodeType[NodeType.restTask]:
- node = new RestTask(this.createId(), name, type, new Position(top, left), []);
- break;
- case NodeType[NodeType.intermediateCatchEvent]:
- node = new IntermediateCatchEvent(this.createId(), name, type, new Position(top, left), []);
- break;
- case NodeType[NodeType.scriptTask]:
- node = new ScriptTask(this.createId(), name, type, new Position(top, left), []);
- break;
- default:
- node = new WorkflowNode(this.createId(), name, type, new Position(top, left), []);
- break;
+ public getNodes(): WorkflowNode[] {
+ return this.planModel.nodes;
+ }
+
+ public addConnection(sourceId: string, targetId: string) {
+ const node = this.getNodeMap().get(sourceId);
+ if (node) {
+ const index = node.connection.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);
+ if (index === -1) {
+ const sequenceFlow: SequenceFlow = { sourceRef: sourceId, targetRef: targetId };
+ node.connection.push(sequenceFlow);
+ }
}
+ }
- this.getProcess().push(node);
- return node;
+ public deleteConnection(sourceId: string, targetId: string) {
+ const node = this.getNodeMap().get(sourceId);
+ if (node) {
+ const index = node.connection.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);
+ if (index !== -1) {
+ node.connection.splice(index, 1);
+ }
+ }
}
- public deleteNode(nodeId: string): WorkflowNode {
+ public deleteNode(parentId: string, nodeId: string): WorkflowNode {
+ const nodeMap = this.getNodeMap();
+
+ const nodes = this.getChildrenNodes(parentId);
+
// delete related connections
- this.getProcess().forEach(node => this.deleteSequenceFlow(node.id, nodeId));
+ nodes.forEach(node => this.deleteConnection(node.id, nodeId));
// delete current node
- const index = this.getProcess().findIndex(node => node.id === nodeId);
+ const index = nodes.findIndex(node => node.id === nodeId);
if (index !== -1) {
- const node = this.getProcess().splice(index, 1)[0];
- node.sequenceFlows = [];
+ const node = nodes.splice(index, 1)[0];
+ node.connection = [];
return node;
}
- return undefined;
+ return null;
}
- public addSequenceFlow(sourceId: string, targetId: string) {
- const node = this.getNodeById(sourceId);
- if (node) {
- const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);
- if (index === -1) {
- node.sequenceFlows.push(new SequenceFlow(sourceId, targetId));
- }
+ public addChild(parentId: string, child: WorkflowNode) {
+ this.getChildrenNodes(parentId).push(child);
+ }
+
+ public deleteChild(node: SubProcess, id: string): WorkflowNode {
+ const index = node.children.findIndex(child => child.id === id);
+ if (index !== -1) {
+ const deletedNode = node.children.splice(index, 1);
+ return deletedNode[0];
}
+
+ return null;
}
- public deleteSequenceFlow(sourceId: string, targetId: string) {
- const node = this.getNodeById(sourceId);
- if (node) {
- const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);
- if (index !== -1) {
- node.sequenceFlows.splice(index, 1);
+ public updateRestConfig(restConfigs: RestConfig[]): void {
+ this.planModel.configs = { restConfigs: restConfigs };
+ // console.log(this.planModel.configs);
+ }
+
+ public getNodeMap(): Map<string, WorkflowNode> {
+ const map = new Map<string, WorkflowNode>();
+ this.toNodeMap(this.planModel.nodes, map);
+ return map;
+ }
+
+ private toNodeMap(nodes: WorkflowNode[], map: Map<string, WorkflowNode>) {
+ nodes.forEach(node => {
+ if (node.type === 'subProcess') {
+ this.toNodeMap((<SubProcess>node).children, map);
}
+ map.set(node.id, node);
+ });
+ }
+
+ public addNode(name: string, type: string, left: number, top: number) {
+ const id = this.createId();
+ const workflowPos = new Position(left, top);
+ const node = this.createNodeByType(id, name, type, workflowPos);
+ this.planModel.nodes.push(node);
+ }
+
+ private createNodeByType(id: string, name: string, type: string, position: Position): WorkflowNode {
+ const bigPosition = new Position(position.left, position.top, 56, 56);
+ const smallPosition = new Position(position.left, position.top, 26, 26);
+ switch (type) {
+ case NodeType[NodeType.startEvent]:
+ let startEventNode: StartEvent = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], parameters: []
+ };
+ return startEventNode;
+ case NodeType[NodeType.endEvent]:
+ let endEventNode: WorkflowNode = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: []
+ };
+ return endEventNode;
+ case NodeType[NodeType.restTask]:
+ let restTaskNode: RestTask = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], produces: [], consumes: [], parameters: [], responses: []
+ };
+ return restTaskNode;
+ case NodeType[NodeType.errorStartEvent]:
+ case NodeType[NodeType.errorEndEvent]:
+ let errorEventNode: ErrorEvent = {
+ id: id, type: type, name: '', parentId: this.rootNodeId,
+ position: smallPosition, connection: [], parameter: new Parameter('errorRef', '', ValueSource[ValueSource.String])
+ };
+ return errorEventNode;
+ case NodeType[NodeType.toscaNodeManagementTask]:
+ let toscaNodeTask: ToscaNodeTask = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], input: [], output: [], template: new NodeTemplate()
+ };
+ return toscaNodeTask;
+ case NodeType[NodeType.subProcess]:
+ let subProcess: SubProcess = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], children: []
+ };
+ return subProcess;
+ case NodeType[NodeType.intermediateCatchEvent]:
+ let intermediateCatchEvent: IntermediateCatchEvent = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], timerEventDefinition: <TimerEventDefinition>{ type: TimerEventDefinitionType[TimerEventDefinitionType.timeDuration] }
+ };
+ return intermediateCatchEvent;
+ case NodeType[NodeType.scriptTask]:
+ let scriptTask: ScriptTask = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], scriptFormat: 'JavaScript'
+ };
+ return scriptTask;
+ case NodeType[NodeType.exclusiveGateway]:
+ case NodeType[NodeType.parallelGateway]:
+ let getway: WorkflowNode = {
+ id: id, type: type, name: '', parentId: this.rootNodeId,
+ position: smallPosition, connection: []
+ };
+ return getway;
+ default:
+ let node: WorkflowNode = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: []
+ };
+ return node;
}
}
+ public isNode(object: any): boolean {
+ return undefined !== object.type;
+ }
+
public getSequenceFlow(sourceRef: string, targetRef: string): SequenceFlow {
const node = this.getNodeById(sourceRef);
if (node) {
- const sequenceFlow = node.sequenceFlows.find(tmp => tmp.targetRef === targetRef);
+ const sequenceFlow = node.connection.find(tmp => tmp.targetRef === targetRef);
return sequenceFlow;
} else {
return undefined;
@@ -123,6 +286,9 @@ export class ModelService {
case NodeType[NodeType.startEvent]:
params.push(this.loadOutput4StartEvent(<StartEvent>node));
break;
+ case NodeType[NodeType.toscaNodeManagementTask]:
+ params.push(this.loadOutput4ToscaNodeTask(<ToscaNodeTask>node));
+ break;
case NodeType[NodeType.restTask]:
params.push(this.loadOutput4RestTask(<RestTask>node));
break;
@@ -135,54 +301,73 @@ export class ModelService {
}
private loadOutput4StartEvent(node: StartEvent): PlanTreeviewItem {
- const startItem = new PlanTreeviewItem(node.name, `[${node.id}]`, []);
+ const startItem = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);
node.parameters.map(param =>
startItem.children.push(new PlanTreeviewItem(param.name, `[${param.name}]`, [])));
return startItem;
}
+ private loadOutput4ToscaNodeTask(node: ToscaNodeTask): PlanTreeviewItem {
+ const item = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);
+ item.children.push(this.createStatusCodeTreeViewItem(node.id));
+ const responseItem = this.createResponseTreeViewItem(node.id);
+ item.children.push(responseItem);
+
+ node.output.map(param =>
+ responseItem.children.push(new PlanTreeviewItem(param.name, `${responseItem.value}.[${param.name}]`, [])));
+ return item;
+ }
+
private loadOutput4RestTask(node: RestTask): PlanTreeviewItem {
- const item = new PlanTreeviewItem(node.name, `[${node.id}]`, []);
+ const item = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);
item.children.push(this.createStatusCodeTreeViewItem(node.id));
if (node.responses.length !== 0) { // load rest responses
const responseItem = this.createResponseTreeViewItem(node.id);
item.children.push(responseItem);
+ // todo: should list all available response or only the first one?
if (node.responses[0]) {
- const swagger = this.configService.getSwaggerInfo(node.serviceName, node.serviceVersion);
- const swaggerDefinition = this.configService.getDefinition(swagger, node.responses[0].schema.$ref);
- this.loadParamsBySwaggerDefinition(responseItem, swagger, <SwaggerModelSimple>swaggerDefinition);
+ const swagger = this.restService.getSwaggerInfo(node.restConfigId);
+ const SwaggerReferenceObject = node.responses[0].schema as SwaggerReferenceObject;
+ const swaggerDefinition = this.restService.getDefinition(swagger, SwaggerReferenceObject.$ref);
+ this.loadParamsBySwaggerDefinition(responseItem, swagger, swaggerDefinition);
}
}
return item;
}
- private createStatusCodeTreeViewItem(nodeId: string): PlanTreeviewItem {
- return new PlanTreeviewItem('statusCode', `[${nodeId}].[statusCode]`, []);
- }
-
- private createResponseTreeViewItem(nodeId: string): PlanTreeviewItem {
- return new PlanTreeviewItem('response', `[${nodeId}].[responseBody]`, []);
- }
-
- private loadParamsBySwaggerDefinition(parentItem: PlanTreeviewItem, swagger: Swagger, definition: SwaggerModelSimple) {
+ private loadParamsBySwaggerDefinition(parentItem: PlanTreeviewItem, swagger: Swagger, definition: any) {
Object.getOwnPropertyNames(definition.properties).map(key => {
const property = definition.properties[key];
const value = `${parentItem.value}.[${key}]`;
const propertyItem = new PlanTreeviewItem(key, value, []);
parentItem.children.push(propertyItem);
+ // reference to swagger.ts function getSchemaObject()
if (property instanceof SwaggerReferenceObject) {
- const propertyDefinition = this.configService.getDefinition(swagger, property.$ref);
- this.loadParamsBySwaggerDefinition(propertyItem, swagger,
- <SwaggerModelSimple>propertyDefinition);
+ // handle reference parameter.
+ const propertyDefinition = this.restService.getDefinition(swagger, property.$ref);
+ this.loadParamsBySwaggerDefinition(propertyItem, swagger, propertyDefinition);
+ } else if (property instanceof SwaggerModelSimple) {
+ // handle object parameter.
+ this.loadParamsBySwaggerDefinition(propertyItem, swagger, property);
+ } else {
+ // skip
}
return propertyItem;
});
}
+ private createStatusCodeTreeViewItem(nodeId: string): PlanTreeviewItem {
+ return new PlanTreeviewItem('statusCode', `[${nodeId}].[statusCode]`, []);
+ }
+
+ private createResponseTreeViewItem(nodeId: string): PlanTreeviewItem {
+ return new PlanTreeviewItem('response', `[${nodeId}].[responseBody]`, []);
+ }
+
public getPreNodes(nodeId: string, preNodes: WorkflowNode[]) {
const preNode4CurrentNode = [];
this.getProcess().forEach(node => {
@@ -201,7 +386,7 @@ export class ModelService {
}
public isPreNode(preNode: WorkflowNode, id: string): boolean {
- const targetNode = preNode.sequenceFlows.find(connection => connection.targetRef === id);
+ const targetNode = preNode.connection.find(connection => connection.targetRef === id);
return targetNode !== undefined;
}
@@ -210,15 +395,62 @@ export class ModelService {
}
private createId() {
- const idSet = new Set();
- this.getProcess().forEach(node => idSet.add(node.id));
+ const nodeMap = this.getNodeMap();
- for (let i = 0; i < idSet.size; i++) {
- if (!idSet.has('node' + i)) {
- return 'node' + i;
+ for (let i = 0; i < nodeMap.size; i++) {
+ const key = 'node' + i;
+ if (!nodeMap.get(key)) {
+ return key;
}
}
- return 'node' + idSet.size;
+ return 'node' + nodeMap.size;
+ }
+
+ public getChildrenNodes(parentId: string): WorkflowNode[] {
+ if (!parentId || parentId === this.rootNodeId) {
+ return this.planModel.nodes;
+ } else {
+ const node = this.getNodeMap().get(parentId);
+ if (node.type === 'subProcess') {
+ return (<SubProcess>node).children;
+ } else {
+ return [];
+ }
+ }
+ }
+
+ public changeParent(id: string, originalParentId: string, targetParentId: string) {
+ if (originalParentId === targetParentId) {
+ return;
+ }
+
+ const node: WorkflowNode = this.deleteNode(originalParentId, id);
+ node.parentId = targetParentId;
+
+ if (targetParentId) {
+ this.addChild(targetParentId, node);
+ } else {
+ this.planModel.nodes.push(node);
+ }
+ }
+
+ public updatePosition(id: string, left: number, top: number, width: number, height: number) {
+ const node = this.getNodeMap().get(id);
+ node.position.left = left;
+ node.position.top = top;
+ node.position.width = width;
+ node.position.height = height;
+ }
+
+ public isDescendantNode(node: WorkflowNode, descendantId: string): boolean {
+ if (NodeType[NodeType.subProcess] !== node.type) {
+ return false;
+ }
+ const tmp = (<SubProcess>node).children.find(child => {
+ return child.id === descendantId || (NodeType[NodeType.subProcess] === child.type && this.isDescendantNode(<SubProcess>child, descendantId));
+ });
+
+ return tmp !== undefined;
}
}
diff --git a/sdc-workflow-designer-ui/src/app/services/rest.service.ts b/sdc-workflow-designer-ui/src/app/services/rest.service.ts
new file mode 100644
index 00000000..db69d78b
--- /dev/null
+++ b/sdc-workflow-designer-ui/src/app/services/rest.service.ts
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+import { Injectable } from '@angular/core';
+import { Http, RequestOptionsArgs } from '@angular/http';
+import { Observable } from 'rxjs/Rx';
+import { isNullOrUndefined } from 'util';
+
+import { SwaggerMethod } from '../model/swagger';
+import { SwaggerResponse } from '../model/swagger';
+import { Swagger, SwaggerSchemaObject } from '../model/swagger';
+import { RestConfig } from '../model/rest-config';
+import { HttpService } from '../util/http.service';
+import { BroadcastService } from './broadcast.service';
+
+@Injectable()
+export class RestService {
+
+ private restConfigs: RestConfig[] = [];
+ private runtimeURL = '/openoapi/catalog/v1/sys/config';
+ private msbPublishServiceURL = '/api/msdiscover/v1/publishservicelist';
+
+ constructor(private broadcastService: BroadcastService, private http: Http) {
+ // this.initSwaggerInfoByMSB();
+ }
+
+ // public addRestConfig(): RestConfig {
+ // let index = 0;
+ // this.restConfigs.forEach(config => {
+ // const currentId = parseInt(config.id);
+ // if (currentId > index) {
+ // index = currentId;
+ // }
+ // });
+
+ // index += 1;
+
+ // const restConfig = new RestConfig(index.toString(), 'new Config', '', '', false);
+ // this.restConfigs.push(restConfig);
+
+ // return restConfig;
+ // }
+
+ // public initSwaggerInfo(restConfig: RestConfig) {
+ // if (restConfig.dynamic && restConfig.definition) {
+ // this.getDynamicSwaggerInfo(restConfig.definition).subscribe(response => restConfig.swagger = new Swagger(response));
+ // } else {
+ // restConfig.swagger = new Swagger(restConfig.swagger);
+ // }
+ // }
+
+ public getRestConfigs() {
+ return this.restConfigs;
+ }
+
+ // public getDynamicSwaggerInfo(url: string): Observable<any> {
+ // const options: any = {
+ // headers: {
+ // Accept: 'application/json',
+ // },
+ // };
+ // return this.httpService.get(url, options);
+ // }
+
+ public getSwaggerInfo(id: string): Swagger {
+ const restConfig = this.restConfigs.find(tmp => tmp.id === id);
+ return restConfig === undefined ? undefined : restConfig.swagger;
+ }
+
+ public getResponseParameters(swagger: Swagger, interfaceUrl: string, operation: string): SwaggerResponse[] {
+ const path = swagger.paths[interfaceUrl];
+ const method: SwaggerMethod = path[operation];
+ let responses: SwaggerResponse[] = [];
+
+ for (const key of Object.keys(method.responses)) {
+ if (key.startsWith('20') && method.responses[key].schema && method.responses[key].schema.$ref) {
+ let response: SwaggerResponse = method.responses[key];
+ responses.push(response);
+ }
+ }
+
+ return responses;
+ }
+
+ public getDefinition(swagger: Swagger, position: string): SwaggerSchemaObject {
+ const definitionName = position.substring('#/definitions/'.length);
+
+ return swagger.definitions[definitionName];
+ }
+
+ private initSwaggerInfoByMSB(): void {
+ const options: any = {
+ headers: {
+ Accept: 'application/json',
+ }
+ };
+ let restConfigs = this.restConfigs;
+ this.http.get(this.runtimeURL).subscribe(runtimeResponse => {
+ const tenant = runtimeResponse.json().tenant;
+ console.log('Current namespace is:' + tenant);
+ this.http.get(this.msbPublishServiceURL, { params: { namespace: tenant } }).subscribe(serviceResponse => {
+ if (!Array.isArray(serviceResponse.json())) {
+ return;
+ }
+ const services = serviceResponse.json();
+ const protocel = location.protocol.slice(0, location.protocol.length - 1);
+ const swaggerObservableArray: Observable<any>[] = [];
+ services.forEach(serviceInfo => {
+ if ('REST' === serviceInfo.protocol && protocel === serviceInfo.publish_protocol) {
+ // this service don't have sawgger file.
+ if ('/activiti-rest' !== serviceInfo.publish_url) {
+ const id = serviceInfo.serviceName + '.' + serviceInfo.version;
+ restConfigs.push(new RestConfig(id, serviceInfo.serviceName, serviceInfo.version, serviceInfo.publish_url));
+ let swaggerUrl = '';
+ if (undefined !== serviceInfo.swagger_url && '' !== serviceInfo.swagger_url) {
+ swaggerUrl = serviceInfo.publish_url + '/' + serviceInfo.swagger_url;
+ } else {
+ // default swagger url is: '/swagger.json'
+ swaggerUrl = serviceInfo.publish_url + '/swagger.json';
+ }
+ swaggerObservableArray.push(this.http.get(swaggerUrl, options).timeout(5000).catch((error): Observable<any> => {
+ console.log('Request swagger from:"' + swaggerUrl + '" faild!');
+ return Observable.of(null);
+ }));
+ }
+ }
+ });
+ Observable.forkJoin(swaggerObservableArray).subscribe(
+ responses => {
+ let deleteArray: number[] = [];
+ responses.forEach((response, index) => {
+ // mark http get failed request index or set the swagger into restConfigs
+ if (null === response) {
+ deleteArray.push(index);
+ } else {
+ try {
+ const swagger = response.json();
+ restConfigs[index].swagger = new Swagger(swagger);
+ } catch (e) {
+ deleteArray.push(index);
+ console.warn('Do not support this sawgger file format:' + response.text());
+ }
+ }
+ });
+ console.log('Get all swagger file finish.');
+ // delete failed request from all restConfigs array
+ deleteArray.reverse();
+ deleteArray.forEach(deleteIndex => {
+ restConfigs.splice(deleteIndex, 1);
+ });
+ this.broadcastService.broadcast(this.broadcastService.updateModelRestConfig, restConfigs);
+ console.log('Load all swagger finished.');
+ }
+ );
+ });
+ });
+ }
+}
+
diff --git a/sdc-workflow-designer-ui/src/app/services/workflow.service.ts b/sdc-workflow-designer-ui/src/app/services/workflow.service.ts
index aba8aa21..75382269 100644
--- a/sdc-workflow-designer-ui/src/app/services/workflow.service.ts
+++ b/sdc-workflow-designer-ui/src/app/services/workflow.service.ts
@@ -41,7 +41,7 @@ export class WorkflowService {
}
this.broadcastWorkflows();
});
- this.broadcastService.workflow.subscribe(workflow => this.planModel = workflow);
+ this.broadcastService.planModel.subscribe(workflow => this.planModel = workflow);
}
public save(): Observable<boolean> {