split element by type 01/27801/1
authorLvbo163 <lv.bo163@zte.com.cn>
Wed, 10 Jan 2018 07:05:39 +0000 (15:05 +0800)
committerLvbo163 <lv.bo163@zte.com.cn>
Wed, 10 Jan 2018 07:05:39 +0000 (15:05 +0800)
split elements by type in toolbar

Issue-ID: SDC-895

Change-Id: I0254c9c5f938df80942d60ffefe4b8577c788233
Signed-off-by: Lvbo163 <lv.bo163@zte.com.cn>
52 files changed:
sdc-workflow-designer-ui/package.json
sdc-workflow-designer-ui/src/app/app.component.css
sdc-workflow-designer-ui/src/app/app.component.html
sdc-workflow-designer-ui/src/app/app.module.ts
sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.ts [deleted file]
sdc-workflow-designer-ui/src/app/components/container/container.component.css [moved from sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.css with 100% similarity]
sdc-workflow-designer-ui/src/app/components/container/container.component.html [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/container/container.component.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.css [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.html
sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.ts
sdc-workflow-designer-ui/src/app/components/menu/menus.component.css [moved from sdc-workflow-designer-ui/src/app/components/menu/menu.component.css with 100% similarity]
sdc-workflow-designer-ui/src/app/components/menu/menus.component.html [moved from sdc-workflow-designer-ui/src/app/components/menu/menu.component.html with 100% similarity]
sdc-workflow-designer-ui/src/app/components/menu/menus.component.spec.ts [moved from sdc-workflow-designer-ui/src/app/components/menu/menu.component.spec.ts with 100% similarity]
sdc-workflow-designer-ui/src/app/components/menu/menus.component.ts [moved from sdc-workflow-designer-ui/src/app/components/menu/menu.component.ts with 91% similarity]
sdc-workflow-designer-ui/src/app/components/node/node.component.css
sdc-workflow-designer-ui/src/app/components/node/node.component.html
sdc-workflow-designer-ui/src/app/components/node/node.component.ts
sdc-workflow-designer-ui/src/app/components/parameter-tree/parameter-tree.component.ts
sdc-workflow-designer-ui/src/app/components/property/properties.component.html
sdc-workflow-designer-ui/src/app/components/property/properties.component.ts
sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task-parameters/rest-task-parameters.component.ts
sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task.component.ts
sdc-workflow-designer-ui/src/app/components/sequence-flow/sequence-flow.component.ts
sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.css
sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.html
sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.ts
sdc-workflow-designer-ui/src/app/directive/drag-select/drag-select.directive.ts [deleted file]
sdc-workflow-designer-ui/src/app/directive/resizeable/resizable.directive.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/rest-config.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/topology/node-template.ts [moved from sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.html with 69% similarity]
sdc-workflow-designer-ui/src/app/model/value-source.enum.ts
sdc-workflow-designer-ui/src/app/model/workflow/end-event.ts
sdc-workflow-designer-ui/src/app/model/workflow/error-event.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/workflow/intermediate-catch-event.ts
sdc-workflow-designer-ui/src/app/model/workflow/node-type.enum.ts
sdc-workflow-designer-ui/src/app/model/workflow/parameter.ts
sdc-workflow-designer-ui/src/app/model/workflow/rest-parameter.ts
sdc-workflow-designer-ui/src/app/model/workflow/rest-task.ts
sdc-workflow-designer-ui/src/app/model/workflow/script-task.ts
sdc-workflow-designer-ui/src/app/model/workflow/start-event.ts
sdc-workflow-designer-ui/src/app/model/workflow/sub-process.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/workflow/timer-event-definition.ts
sdc-workflow-designer-ui/src/app/model/workflow/tosca-node-task.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/workflow/workflow-element.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/model/workflow/workflow-node.ts
sdc-workflow-designer-ui/src/app/services/broadcast.service.ts
sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts
sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts
sdc-workflow-designer-ui/src/app/services/model.service.ts
sdc-workflow-designer-ui/src/app/services/rest.service.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/workflow.service.ts

index 8a58795..cf4c70c 100644 (file)
@@ -25,6 +25,8 @@
     "bootstrap": "4.0.0-alpha.6",
     "core-js": "^2.4.1",
     "font-awesome": "^4.7.0",
+    "jquery": "^3.2.1",
+    "jquery-ui": "^1.12.1",
     "jsplumb": "2.5.0",
     "ngx-bootstrap": "^1.9.1",
     "ngx-tree-select": "^0.11.1",
index fdafa45..9516693 100644 (file)
@@ -9,19 +9,86 @@
  * Contributors:\r
  *     ZTE - initial API and implementation and/or initial documentation\r
  */\r
- .main-content-wrapper{\r
+ .loading-div{\r
+    position: absolute;\r
+    top: 0;\r
+    width: 100%;\r
+    height: 100%;\r
+    background-color: white;\r
+}\r
+\r
+.loading-div div{\r
+    position: relative;\r
+    top: calc(50% - 36px);\r
+    left: calc(50% - 36px);\r
+}\r
+\r
+.loading-div div:not(:required) {\r
+    -moz-animation: three-quarters-loader 1.5s infinite linear;\r
+    -webkit-animation: three-quarters-loader 1.5s infinite linear;\r
+    animation: three-quarters-loader 1.5s infinite linear;\r
+    box-sizing: border-box;\r
+    display: inline-block;\r
+    overflow: hidden;\r
+    text-indent: -9999px;\r
+    border: 5px solid #1dadfc;\r
+    border-right-color: transparent;\r
+    border-radius: 36px;\r
+    width: 72px;\r
+    height: 72px;\r
+}\r
+\r
+@-moz-keyframes three-quarters-loader {\r
+    0% {\r
+        -moz-transform: rotate(0deg);\r
+        transform: rotate(0deg)\r
+    }\r
+    to {\r
+        -moz-transform: rotate(1turn);\r
+        transform: rotate(1turn)\r
+    }\r
+}\r
+\r
+@-webkit-keyframes three-quarters-loader {\r
+    0% {\r
+        -webkit-transform: rotate(0deg);\r
+        transform: rotate(0deg)\r
+    }\r
+    to {\r
+        -webkit-transform: rotate(1turn);\r
+        transform: rotate(1turn)\r
+    }\r
+}\r
+\r
+@keyframes three-quarters-loader {\r
+    0% {\r
+        -moz-transform: rotate(0deg);\r
+        -ms-transform: rotate(0deg);\r
+        -webkit-transform: rotate(0deg);\r
+        transform: rotate(0deg)\r
+    }\r
+    to {\r
+        -moz-transform: rotate(1turn);\r
+        -ms-transform: rotate(1turn);\r
+        -webkit-transform: rotate(1turn);\r
+        transform: rotate(1turn)\r
+    }\r
+}\r
+\r
+.main-content-wrapper{\r
     height: 100%;\r
     background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMTEgMTEiPjxkZWZzPjxzdHlsZT4uY2xzLTF7aXNvbGF0aW9uOmlzb2xhdGU7fS5jbHMtMntmaWxsOiNmYWZiZmQ7fS5jbHMtM3tmaWxsOiNlY2VkZWY7ZmlsbC1ydWxlOmV2ZW5vZGQ7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5iYWNrZ3JvdW5kLWltYWdlc192MjwvdGl0bGU+PGc+PGltYWdlIHdpZHRoPSIxMSIgaGVpZ2h0PSIxMSIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBc0FBQUFMQ0FJQUFBQW16dUJ4QUFBQUNYQklXWE1BQUFzU0FBQUxFZ0hTM1g3OEFBQUFFMGxFUVZRWVYyUDRUd2d3RUZJd3FvSmtGUUF3eFdtbDRtUGRyd0FBQUFCSlJVNUVya0pnZ2c9PSIvPjwvZz48ZyBpZD0i55+p5b2iXzEiIGRhdGEtbmFtZT0i55+p5b2iIDEiIGNsYXNzPSJjbHMtMSI+PGcgaWQ9IuefqeW9ol8xLTIiIGRhdGEtbmFtZT0i55+p5b2iIDEiPjxyZWN0IGNsYXNzPSJjbHMtMiIgd2lkdGg9IjExIiBoZWlnaHQ9IjExIi8+PC9nPjwvZz48ZyBjbGFzcz0iY2xzLTEiPjxnPjxwb2x5Z29uIGNsYXNzPSJjbHMtMyIgcG9pbnRzPSIxMCAwIDEwIDEwIDAgMTAgMCAxMSAxMCAxMSAxMC45MiAxMSAxMC45MiAwIDEwIDAiLz48L2c+PC9nPjwvc3ZnPg==);\r
     background-size: 11px;\r
 }\r
 \r
-.toolbar{\r
+.tool-bar{\r
     position: fixed;\r
     top: 0px;\r
     left: 0px;\r
     width: 200px;\r
     height: 100%;\r
     background-color: white;\r
+    overflow-y: auto;\r
 }\r
 \r
 .design-area{\r
@@ -32,7 +99,7 @@
     padding: 20px;\r
 }\r
 \r
-.design-menu{\r
+.design-menus{\r
     display: block;\r
     height: 30px;\r
     margin-bottom: 10px;\r
index 1917b83..9f0e5cf 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 -->
-
 <div class="main-content-wrapper">
-    <b4t-toolbar class="toolbar"></b4t-toolbar>
+    <b4t-toolbar class="tool-bar"></b4t-toolbar>
     <div class="design-area">
-        <b4t-menu class="design-menu"></b4t-menu>
-        <b4t-canvas></b4t-canvas>
+        <menus class="design-menus"></menus>
+        <b4t-container class="design-container"></b4t-container>
     </div>
-    <b4t-properties></b4t-properties>
-    <b4t-sequence-flow></b4t-sequence-flow>
 </div>
index 199bfcd..07ccebc 100644 (file)
@@ -15,6 +15,8 @@ import { BrowserModule } from '@angular/platform-browser';
 import { NgModule } from '@angular/core';
 import { NgxTreeSelectModule } from 'ngx-tree-select';
 
+import { AccordionModule } from 'ngx-bootstrap/accordion';
+
 import { AppComponent } from './app.component';
 import { JsPlumbService } from "./services/jsplumb.service";
 import { NodeComponent } from "./components/node/node.component";
@@ -29,10 +31,9 @@ import { HttpModule } from "@angular/http";
 import { RouterModule } from "@angular/router";
 import { BroadcastService } from "./services/broadcast.service";
 import { PropertiesComponent } from "./components/property/properties.component";
-import { CanvasComponent } from "./components/canvas/canvas.component";
 import { StartEventParametersComponent } from "./components/property/start-event-parameters/start-event-parameters.component";
 import { ParameterComponent } from "./components/parameter/parameter.component";
-import { MenuComponent } from "./components/menu/menu.component";
+import { MenusComponent } from "./components/menu/menus.component";
 import { MicroserviceDetailComponent } from "./components/menu/microservice/microservice-detail/microservice-detail.component";
 import { MicroserviceComponent } from "./components/menu/microservice/microservice.component";
 import { MicroserviceListComponent } from "./components/menu/microservice/microservice-list/microservice-list.component";
@@ -46,18 +47,20 @@ import { SwaggerTreeConverterService } from "./services/swagger-tree-converter.s
 import { IntermediateCatchEventComponent } from "./components/property/intermediate-catch-event/intermediate-catch-event.component";
 import { SequenceFlowComponent } from "./components/sequence-flow/sequence-flow.component";
 import { ScriptTaskComponent } from "./components/property/script-task/script-task.component";
-import { DragSelectDirective } from "./directive/drag-select/drag-select.directive";
 import { WorkflowsComponent } from "./components/menu/workflows/workflows.component";
 import { ModelService } from './services/model.service';
+import { ContainerComponent } from './components/container/container.component';
+import { RestService } from './services/rest.service';
+import { ResizableDirective } from './directive/resizeable/resizable.directive';
 
 @NgModule({
     declarations: [
         AppComponent,
-        CanvasComponent,
-        DragSelectDirective,
+        ContainerComponent,
+        ResizableDirective,
         EditablePropertyComponent,
         IntermediateCatchEventComponent,
-        MenuComponent,
+        MenusComponent,
         MicroserviceComponent,
         MicroserviceDetailComponent,
         MicroserviceListComponent,
@@ -74,6 +77,7 @@ import { ModelService } from './services/model.service';
         WorkflowsComponent,
     ],
     imports: [
+        AccordionModule.forRoot(),
         BrowserAnimationsModule,
         BrowserModule,
         HttpModule,
@@ -96,6 +100,7 @@ import { ModelService } from './services/model.service';
         DataAccessService,
         HttpService,
         JsPlumbService,
+        RestService,
         SwaggerTreeConverterService,
         WorkflowConfigService,
         ModelService,
diff --git a/sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.ts b/sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.ts
deleted file mode 100644 (file)
index 1cf197d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * 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 { AfterViewInit, Component, HostListener } from '@angular/core';
-
-import { BroadcastService } from '../../services/broadcast.service';
-import { JsPlumbService } from '../../services/jsplumb.service';
-import { ActivatedRoute } from "@angular/router";
-import { DataAccessService } from "../../services/data-access/data-access.service";
-import { WorkflowService } from "../../services/workflow.service";
-import { PlanModel } from "../../model/workflow/plan-model";
-import { ModelService } from "../../services/model.service";
-import { SequenceFlow } from "../../model/workflow/sequence-flow";
-import { WorkflowNode } from "../../model/workflow/workflow-node";
-
-/**
- * main canvas, it contains two parts: canvas and node property component
- * bpmn task nodes can be dropped into this canvas, and then the workflow can be edit
- */
-@Component({
-    selector: 'b4t-canvas',
-    styleUrls: ['./canvas.component.css'],
-    templateUrl: 'canvas.component.html',
-})
-export class CanvasComponent implements AfterViewInit {
-    private currentType: string; // WorkflowNode, SequenceFlow
-    private currentWorkflowNode: WorkflowNode;
-    private currentSequenceFlow: SequenceFlow;
-
-
-    constructor(private broadcastService: BroadcastService,
-        private dataAccessService: DataAccessService,
-        private jsPlumbService: JsPlumbService,
-        private route: ActivatedRoute,
-        private workflowService: WorkflowService,
-        private processService: ModelService) {
-    }
-
-    ngOnInit(): void {
-        // this.route.queryParams.subscribe(params => {
-        //     if (params.id) {
-        //         this.dataAccessService.catalogService.loadWorkflow(params.id).subscribe(workflow => {
-        //             this.workflowService.workflow = workflow;
-        //         });
-        //     }
-        // });
-    }
-
-    public ngAfterViewInit() {
-        this.jsPlumbService.buttonDroppable();
-        this.broadcastService.currentSequenceFlow$.subscribe(sequenceFlow => this.currentSequenceFlow = sequenceFlow);
-        this.broadcastService.currentWorkflowNode$.subscribe(workflowNode => this.currentWorkflowNode = workflowNode);
-        this.broadcastService.currentType$.subscribe(type => this.currentType = type);
-    }
-
-    public canvasClick() {
-        this.broadcastService.broadcast(this.broadcastService.showProperty, false);
-        this.broadcastService.broadcast(this.broadcastService.showSequenceFlow, false);
-    }
-
-    @HostListener('window:keyup.delete', ['$event']) ondelete(event: KeyboardEvent) {
-        if (this.currentType === 'WorkflowNode') {
-            this.jsPlumbService.remove(this.currentWorkflowNode.id);
-            this.processService.deleteNode(this.currentWorkflowNode.id);
-        } else if (this.currentType === 'SequenceFlow') {
-            this.processService.deleteSequenceFlow(this.currentSequenceFlow.sourceRef, this.currentSequenceFlow.targetRef);
-            this.jsPlumbService.deleteConnect(this.currentSequenceFlow.sourceRef, this.currentSequenceFlow.targetRef);
-        }
-    }
-
-
-    public getWorkflow(): PlanModel {
-        return this.workflowService.planModel;
-    }
-}
diff --git a/sdc-workflow-designer-ui/src/app/components/container/container.component.html b/sdc-workflow-designer-ui/src/app/components/container/container.component.html
new file mode 100644 (file)
index 0000000..0d9c522
--- /dev/null
@@ -0,0 +1,22 @@
+<!--
+/**
+ * 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
+ */
+-->
+
+<div #mainContainer id="canvas" class="canvas" (mousedown)="canvasMouseDown($event)">
+    <div id="node-selector" #nodeSelector></div>
+    <b4t-node *ngFor="let node of modelService.getNodes()" [node]="node" [rank]="10"></b4t-node>
+</div>
+
+<b4t-properties></b4t-properties>
+
+<b4t-sequence-flow></b4t-sequence-flow>
diff --git a/sdc-workflow-designer-ui/src/app/components/container/container.component.ts b/sdc-workflow-designer-ui/src/app/components/container/container.component.ts
new file mode 100644 (file)
index 0000000..f35c248
--- /dev/null
@@ -0,0 +1,164 @@
+/**
+ * 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 { AfterViewChecked, AfterViewInit, Component, ElementRef, HostListener, OnInit, OnDestroy, ViewChild } from '@angular/core';
+
+import { SequenceFlow } from '../../model/workflow/sequence-flow';
+import { WorkflowElement } from '../../model/workflow/workflow-element';
+import { WorkflowNode } from '../../model/workflow/workflow-node';
+import { BroadcastService } from '../../services/broadcast.service';
+import { JsPlumbService } from '../../services/jsplumb.service';
+import { ModelService } from '../../services/model.service';
+
+/**
+ * main canvas, it contains two parts: canvas and node property component
+ * bpmn task nodes can be dropped into this canvas, and then the workflow can be edit
+ */
+@Component({
+    selector: 'b4t-container',
+    templateUrl: 'container.component.html',
+    styleUrls: ['./container.component.css']
+})
+export class ContainerComponent implements AfterViewChecked, AfterViewInit, OnInit, OnDestroy {
+    public allNotes: WorkflowNode[];
+    @ViewChild('nodeSelector') nodeSelector: ElementRef;
+    @ViewChild('mainContainer') mainContainer: ElementRef;
+
+    private isSelecting = false;
+    private selectedElements: WorkflowElement[] = [];
+    private showProperties = false;
+    private needInitSequence = false;
+
+    constructor(private broadcastService: BroadcastService, private jsPlumbService: JsPlumbService,
+        public modelService: ModelService) {
+    }
+
+    @HostListener('window:keyup.delete', ['$event']) ondelete(event: KeyboardEvent) {
+        if (this.showProperties || 0 >= this.selectedElements.length) {
+            return;
+        }
+        this.selectedElements.forEach(element => {
+            if (this.modelService.isNode(element)) {
+                let selectNode = element as WorkflowNode;
+                const parentId = this.jsPlumbService.getParentNodeId(selectNode.id);
+                this.jsPlumbService.remove(selectNode);
+                this.modelService.deleteNode(parentId, selectNode.id);
+            } else {
+                let sequenceFlow = element as SequenceFlow;
+                this.modelService.deleteConnection(sequenceFlow.sourceRef, sequenceFlow.targetRef);
+                this.jsPlumbService.deleteConnect(sequenceFlow.sourceRef, sequenceFlow.targetRef);
+            }
+        });
+        this.selectedElements = [];
+    }
+
+    @HostListener('document:mouseup', ['$event']) onmouseup() {
+        if (this.isSelecting) {
+            this.nodeSelector.nativeElement.style.display = 'none';
+            this.mainContainer.nativeElement.onmousemove = null;
+            this.isSelecting = false;
+            this.broadcastService.broadcast(this.broadcastService.showProperty, null);
+            this.broadcastService.broadcast(this.broadcastService.selectedElement, this.selectedElements);
+        }
+    }
+
+    public ngOnInit() {
+        this.jsPlumbService.initJsPlumbInstance(this.modelService.rootNodeId);
+        this.broadcastService.planModel$.subscribe(() => {
+            this.needInitSequence = true;
+        });
+        this.broadcastService.showProperty$.subscribe(element=>{
+            this.showProperties = null !== element;
+        });
+    }
+
+    public ngAfterViewInit() {
+        this.jsPlumbService.canvasDroppable();
+        this.broadcastService.selectedElement$.subscribe(elements => {
+            if (elements) {
+                this.selectedElements = elements;
+            } else {
+                this.selectedElements = [];
+            }
+        });
+    }
+
+    public ngAfterViewChecked() {
+        if (this.needInitSequence) {
+            this.needInitSequence = false;
+            // Add the connection
+            this.jsPlumbService.connectChildrenNodes(this.modelService.rootNodeId);
+        }
+    }
+
+    public ngOnDestroy() {
+        if (this.mainContainer.nativeElement.onmousemove) {
+            this.mainContainer.nativeElement.document.onmousemove = null;
+        }
+    }
+
+    public canvasMouseDown(event) {
+        this.selectedElements = [];
+        this.isSelecting = true;
+        let posx = event.clientX + this.mainContainer.nativeElement.scrollLeft;
+        posx = 220 > posx ? 0 : posx - 220;
+        let posy = event.clientY + this.mainContainer.nativeElement.scrollTop;
+        posy = 60 > posy ? 0 : posy - 60;
+        let element = this.nodeSelector.nativeElement;
+        element.style.left = posx + "px";
+        element.style.top = posy + "px";
+        element.style.width = '0px';
+        element.style.height = '0px';
+        element.style.display = 'block';
+        let curThis = this;
+        this.mainContainer.nativeElement.onmousemove = function (moveEvent) {
+            let movePosx = moveEvent.clientX + curThis.mainContainer.nativeElement.scrollLeft;
+            movePosx = 220 > movePosx ? 0 : movePosx - 220;
+            let movePosy = moveEvent.clientY + curThis.mainContainer.nativeElement.scrollTop;
+            movePosy = 60 > movePosy ? 0 : movePosy - 60;
+            const left = Math.min(movePosx, posx);
+            const top = Math.min(movePosy, posy);
+            const width = Math.abs(posx - movePosx);
+            const height = Math.abs(posy - movePosy);
+            element.style.left = left + "px";
+            element.style.top = top + "px";
+            element.style.width = width + "px";
+            element.style.height = height + "px";
+            curThis.selectNodes(left, top, width, height);
+        };
+    }
+
+    private selectNodes(left: number, top: number, width: number, height: number) {
+        this.selectedElements = [];
+        const allNodes = this.modelService.getNodes();
+        allNodes.forEach(node => {
+            const np = node.position;
+            let selected = false;
+            if (left < np.left) {
+                if ((top < np.top && left + width > np.left && top + height > np.top)
+                    || (top >= np.top && top < np.top + np.height && left + width > np.left)) {
+                    selected = true;
+                }
+            } else if (left < np.left + np.width) {
+                if ((top < np.top && top + height > np.top)
+                    || (top >= np.top && top < np.top + np.height)) {
+                    selected = true;
+                }
+            }
+            if (selected) {
+                this.selectedElements.push(node);
+            }
+        });
+        this.broadcastService.broadcast(this.broadcastService.selectedElement, this.selectedElements);
+    }
+
+}
diff --git a/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.css b/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.css
new file mode 100644 (file)
index 0000000..78475cf
--- /dev/null
@@ -0,0 +1,26 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+ .edit{\r
+    font-size: 24px;\r
+    width: 300px;\r
+    height: 30px;\r
+    border: 1px solid #fff;\r
+}\r
+\r
+.edit:hover{\r
+    border-color: #80bdff;\r
+}\r
+\r
+.edit:focus{\r
+    border-color: #80bdff;\r
+}\r
index a2d9fd5..8dde9f1 100644 (file)
@@ -1,25 +1,5 @@
-<!--
-/**
- * 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
- */
- -->
-<span *ngIf="!isEditing()">
-    <span (dblclick)="startEdit()">{{parameter.value}}</span>
-    <i class="fa fa-edit" (click)="startEdit()"></i>
-</span>
-<span class="row" *ngIf="isEditing()">
-    <span class="col-sm-10">
-        <b4t-parameter [param]="parameter" [showLabel]="showLabel" [valueSource]= "valueSource" [planItems]="planItems"></b4t-parameter>
-    </span>
-    <span class="col-sm-2">
-        <i class="fa fa-check" (click)="completeEdit()"></i>
-    </span>
-</span>
+<input class="edit pull-left" [ngModel]="name" (ngModelChange)="change($event)" (click)="startEdit()" (blur)="stopEdit()"
+(mouseover)="showEditComponent(true)" (mouseout)="showEditComponent(false)">
+<button *ngIf="showEdit" type="button" class="btn blue1 pull-left" (click)="stopEdit();">
+<i class="fa fa-check"></i>
+</button>
index 719d2a6..ea96575 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation
  */
 
-import { AfterViewInit, Component, EventEmitter, Input, Output } from '@angular/core';
-
-import { ValueSource } from '../../model/value-source.enum';
-import { ValueType } from '../../model/value-type.enum';
-import { Parameter} from '../../model/workflow/parameter';
-import { PlanTreeviewItem } from "../../model/plan-treeview-item";
+import { Component, EventEmitter, Input, Output } from '@angular/core';
 
 /**
- * property component presents information of a workflow node.
- * the presented information can be edit in this component.
- * it may load information dynamically. the content may be different for different node type.
+ * node or workflow-line name
  */
 @Component({
     selector: 'b4t-editable-property',
     templateUrl: 'editable-property.component.html',
+    styleUrls: ['./editable-property.component.css']
 })
 export class EditablePropertyComponent {
-    @Input() public parameter: Parameter;
-    @Input() public planItems: PlanTreeviewItem[];
-    @Input() public showLabel: boolean;
-    @Input() public valueSource: ValueSource[];
-    @Output() public parameterChange = new EventEmitter<Parameter>();
+    @Input() public name: string;
+    @Output() public nameChange = new EventEmitter<string>();
+
+    public showEdit = false;
+    public isEditing = false;
 
-    private editing = false;
+    public showEditComponent(isShow: boolean): void {
+        if(isShow){
+            this.showEdit = isShow;
+        }else{
+            if(!this.isEditing){
+                this.showEdit = false;
+            }
+        }
+    }
 
-    public isEditing(): boolean {
-        return this.editing;
+    public startEdit(): void {
+        this.isEditing = true;
     }
 
-    public startEdit() {
-        this.editing = true;
+    public stopEdit(): void {
+        this.isEditing = false;
+        this.showEdit = false;
     }
 
-    public completeEdit() {
-        this.editing = false;
-        this.parameterChange.emit(this.parameter);
+    public change(newName: string) {
+        this.name = newName;
+        this.nameChange.emit(this.name);
     }
 }
@@ -18,11 +18,11 @@ import { BroadcastService } from "../../services/broadcast.service";
 import { PlanModel } from "../../model/workflow/plan-model";
 
 @Component({
-    selector: 'b4t-menu',
-    templateUrl: './menu.component.html',
-    styleUrls: ['./menu.component.css']
+    selector: 'menus',
+    templateUrl: './menus.component.html',
+    styleUrls: ['./menus.component.css']
 })
-export class MenuComponent {
+export class MenusComponent {
     @ViewChild(MicroserviceComponent) public microserviceComponent: MicroserviceComponent;
     @ViewChild(WorkflowsComponent) public workflowsComponent: WorkflowsComponent;
     public currentWorkflow = 'Workflows';
@@ -62,6 +62,7 @@ export class MenuComponent {
             const options = [];
             workflows.forEach((value, key, map) => {
                 options.push({label: value.planName, command: () => {
+                    console.log(`${value.planName} selected`);
                     this.workflowSelected(value.planName, value.plan);
                 }});
             });
@@ -73,7 +74,7 @@ export class MenuComponent {
 
     public workflowSelected(planName: string, workflow: PlanModel) {
         this.currentWorkflow = planName;
-        this.broadcastService.broadcast(this.broadcastService.workflow, workflow);
+        this.broadcastService.broadcast(this.broadcastService.planModel, workflow);
     }
 
     public download() {
index 093892e..af1ce88 100644 (file)
  */\r
 \r
  .node {\r
-    border: 1px solid transparent;\r
     cursor: pointer;\r
     display: inline-block;\r
     position: absolute;\r
     z-index: 2;\r
 }\r
 \r
+.node-icon{\r
+    border-radius: 4px;\r
+}\r
 \r
-.node.active {\r
-    border: 2px solid red !important;\r
-    box-shadow: 2px 2px 19px #444;\r
-    -o-box-shadow: 2px 2px 19px #444;\r
-    -webkit-box-shadow: 2px 2px 19px #444;\r
-    -moz-box-shadow: 2px 2px 19px #fff;\r
-    opacity: 0.9;\r
+.node-icon svg{\r
+    display: block;\r
+    fill: #00ABFF;\r
 }\r
 \r
-.node:hover {\r
-    border: 1px solid #123456;\r
-    box-shadow: 2px 2px 19px #444;\r
-    -o-box-shadow: 2px 2px 19px #444;\r
-    -webkit-box-shadow: 2px 2px 19px #444;\r
-    -moz-box-shadow: 2px 2px 19px #fff;\r
-    opacity: 0.9;\r
+.active {\r
+    outline: 1px solid #00ABFF;\r
 }\r
 \r
 /**\r
 .anchors {\r
     position: absolute;\r
     border-radius: 1em;\r
-    z-index: 20;\r
     display: none;\r
-    background-color: black;\r
-    width: 0;\r
-    height: 0;\r
+    background-color: #2e6f9a;\r
+    width: 12px;\r
+    height: 12px;\r
     cursor: pointer;\r
     -ms-transition: all 0.15s ease-in-out;\r
     transition: all 0.15s ease-in-out;\r
     -o-transition: all 0.15s ease-in-out;\r
 }\r
 \r
-.node:hover .anchors {\r
-    background-color: black;\r
+.node-icon:hover > .anchors {\r
     display: inline-block;\r
-    width: 12px;\r
-    height: 12px;\r
-    z-index: 20;\r
 }\r
 \r
 .anchor-left {\r
-    left: -5px;\r
-    top: 40%;\r
+    left: -6px;\r
+    top: calc(50%);\r
 }\r
 \r
 .anchor-right {\r
-    right: -5px;\r
-    top: 40%;\r
+    right: -6px;\r
+    top: calc(50%);\r
 }\r
 \r
 .anchor-top {\r
-    top: -5px;\r
-    left: 40%;\r
+    top: -6px;\r
+    left: calc(50% - 6px);\r
 }\r
 \r
 .anchor-bottom {\r
-    bottom: -5px;\r
-    left: 40%;\r
+    bottom: -6px;\r
+    left: calc(50% - 6px);\r
 }\r
 \r
-/*right-arrow*/\r
+/*right arrow*/\r
 .right {\r
     width: 10px;\r
     height: 10px;\r
     border-top: 5px transparent dashed;\r
     border-right: 5px transparent dashed;\r
     border-bottom: 5px transparent dashed;\r
-    border-left: 5px black solid;\r
+    border-left: 5px #2e6f9a solid;\r
     overflow: hidden;\r
 }\r
 \r
     left: -2px;\r
 }\r
 \r
-/*left-arrow*/\r
+/*left arrow */\r
 .left {\r
     width: 10px;\r
     height: 10px;\r
     position: absolute;\r
     left: 0;\r
     top: 0;\r
-    z-index: 5;\r
+    z-index: 5; /*ie8-*/\r
     border-top: 5px transparent dashed;\r
     border-left: 5px transparent dashed;\r
     border-bottom: 5px transparent dashed;\r
-    border-right: 5px black solid;\r
+    border-right: 5px #2e6f9a solid;\r
     overflow: hidden;\r
 }\r
 \r
     left: 2px;\r
 }\r
 \r
-/*top-arrow*/\r
+/*top arrow*/\r
 .top {\r
-    width: 9px;\r
-    height: 9px;\r
+    width: 10px;\r
+    height: 10px;\r
     position: absolute;\r
     left: 1px;\r
     z-index: 2;\r
     left: 0;\r
     top: 0;\r
     z-index: 5;\r
-    border-bottom: 5px black solid;\r
+    border-bottom: 5px #2e6f9a solid;\r
     border-left: 5px transparent dashed;\r
     border-right: 5px transparent dashed;\r
     border-top: 5px transparent dashed;\r
 \r
 .top-arrow2 {\r
     top: -2px;\r
-    border-bottom: 4px white solid;\r
+    border-bottom: 5px white solid;\r
 }\r
 \r
-/*bottom-arrow*/\r
+/*bottom arrow*/\r
 .bottom {\r
-    width: 9px;\r
-    height: 9px;\r
+    width: 10px;\r
+    height: 10px;\r
     position: absolute;\r
     left: 1px;\r
     top: 4px;\r
     left: 0;\r
     top: 0;\r
     z-index: 5;\r
-    border-bottom: 4px transparent dashed;\r
-    border-left: 4px transparent dashed;\r
-    border-right: 4px transparent dashed;\r
-    border-top: 4px black solid;\r
+    border-bottom: 5px transparent dashed;\r
+    border-left: 5px transparent dashed;\r
+    border-right: 5px transparent dashed;\r
+    border-top: 5px #2e6f9a solid;\r
     overflow: hidden;\r
 }\r
 \r
 }\r
 \r
 .bottom-arrow2 {\r
-    border-top: 4px white solid;\r
+    border-top: 5px white solid;\r
 }\r
+/**\r
+ * Anchors End\r
+ */\r
 \r
 .node .name {\r
-    padding: 10px 15px;\r
-}\r
-\r
-.node:hover {\r
-    border: 1px dotted #000;\r
-}\r
-\r
-.node.focus {\r
-    border: 1px dotted red;\r
-}\r
-\r
-.startEvent {\r
-    border-radius: 30px;\r
-    border: 1px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    /*background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAWlJREFUeNrsmLGNwjAUhsmJMpLdpYwrlC7OBCg7IEVUjICZALdUcSZghLBBvIE9gulClTBBrqA56TAQO5yQ7v2trbxPn5znJwfDMMw+L1+zjwxgARZgARZgAdafZ25bOJ/Pxpj3FW7btigK6/JgCULo3UrW67WtutVWkiTGmMvlslqtNptNGIZTSTocDlrrKIoWi8VoW8vlcr/fl2WJECKENE0zeEcIgTFO01Qpdfu+beeTI88Y01rHcZzn+W636/veTZIxJs9zxth2u9VaU0p9/0RCiJSyLMvj8ZhlmZRyLFNVVVmWdV2nlOKcT9kg3LSNleTSt8Zqc5Dk3k5f0eYsyavLP9bmI2mCy+e3Nn9Jzy+f17UJITjndV1fr9c4jpVSPkCTXdU3bZRSf0nT2Pqp7XQ6wbwFWIAFWP8Y69HQ/O7SD4bmwPZ2KqV0GERtCYI7hRhjGOP7++FJF7AAC7AAC7AA65OxvgcA+Qikc7YGylkAAAAASUVORK5CYII=");*/\r
-}\r
-\r
-.endEvent {\r
-    border-radius: 30px;\r
-    border: 2px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    /*background-image: url("data:image/png;base64,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");*/\r
-}\r
-\r
-.intermediateCatchEvent {\r
-    border-radius: 30px;\r
-    border: 1px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    background-image: url("data:image/svg+xml;utf8,<?xml version='1.0' encoding='UTF-8' standalone='no'?><svg xmlns='http://www.w3.org/2000/svg' xmlns:oryx='http://www.b3mn.org/oryx' viewBox='1 1 30 30' width='28' height='28' style='fill:transparent' version='1.0'> <defs></defs> <oryx:magnets> <oryx:magnet oryx:cx='16' oryx:cy='16' oryx:default='yes' /> </oryx:magnets> <oryx:docker oryx:cx='16' oryx:cy='16' /> <g pointer-events='fill'> <defs> <radialGradient id='background' cx='10%' cy='10%' r='100%' fx='10%' fy='10%'> <stop offset='0%' stop-color='#ffffff' stop-opacity='1'/> <stop id='fill_el' offset='100%' stop-color='#ffffff' stop-opacity='1'/> </radialGradient> </defs> <circle id='bg_frame' cx='16' cy='16' r='15' stroke='black' stroke-width='1' style='stroke-dasharray: 5.5, 3' />  <circle id='frame2_non_interrupting' cx='16' cy='16' r='12' stroke='black' fill='none' stroke-width='1' style='stroke-dasharray: 4.5, 3' /><circle id='frame' cx='16' cy='16' r='15' stroke='black' fill='none' stroke-width='1'/><circle id='frame2' cx='16' cy='16' r='12' stroke='black' fill='none' stroke-width='1'/><circle id='circle' cx='16' cy='16' r='10' stroke='black' fill='none' stroke-width='1'/> <path id='path1' d='M 16 6 L 16 9 M 21 7 L 19.5 10 M 25 11 L 22 12.5 M 26 16 L 23 16 M 25 21 L 22 19.5 M 21 25 L 19.5 22 M 16 26 L 16 23 M 11 25 L 12.5 22 M 7 21 L 10 19.5 M 6 16 L 9 16 M 7 11 L 10 12.5 M 11 7 L 12.5 10 M 18 9 L 16 16 L 20 16' fill='none' stroke='black' /> <text font-size='11' id='text_name' x='16' y='33' oryx:align='top center' stroke='black'></text></g></svg>");\r
-}\r
-\r
-\r
-.scriptTask {\r
-    border-radius: 8px;\r
-    border: 2px solid rgb(0, 0, 0);\r
-    height: 60px;\r
-    width: 80px;\r
-    background-image: url("data:image/svg+xml;utf8,<?xml version='1.0' encoding='UTF-8' standalone='no'?> <svg    xmlns='http://www.w3.org/2000/svg'    xmlns:svg='http://www.w3.org/2000/svg'    xmlns:oryx='http://www.b3mn.org/oryx'    version='1.0' width='100%' height='100%'>           <g id='scriptTask' transform='scale(1, 1) translate(8,8)'>              <path oryx:anchors='top left' id='paper' style='opacity:1;fill:none;stroke:#000000'             d='M6.402,0.5h14.5c0,0-5.833,2.833-5.833,5.583s4.417,6,4.417,9.167                      s-4.167,5.083-4.167,5.083H0.235c0,0,5-2.667,5-5s-4.583-6.75-4.583-9.25S6.402,0.5,6.402,0.5z'/>          <path oryx:anchors='top left' id='line1' style='opacity:1;fill:none;stroke:#000000;stroke-width:1.5' d='M 3.5 4.5 L 13.5 4.5' />                <path oryx:anchors='top left' id='line2' style='opacity:1;fill:none;stroke:#000000;stroke-width:1.5' d='M 3.8 8.5 L 13.8 8.5' />                <path oryx:anchors='top left'  id='line3' style='opacity:1;fill:none;stroke:#000000;stroke-width:1.5' d='M 6.3 12.5 L 16.3 12.5' />             <path oryx:anchors='top left' id='line4' style='opacity:1;fill:none;stroke:#000000;stroke-width:1.5' d='M 6.5 16.5 L 16.5 16.5' />      </g> </svg> ");\r
-}\r
-\r
-.restTask {\r
-    border-radius: 8px;\r
-    border: 2px solid rgb(0, 0, 0);\r
-    font-size: 10px;\r
+    width: 55px;\r
+    height: 12px;\r
+    text-align: center;\r
+    white-space: nowrap;\r
+    color: #5c6d90;\r
+    line-height: 12px;\r
+    cursor: pointer;\r
+    font-family: Arial;\r
+    font-size: 12px;\r
 }\r
 \r
-.parallelGateway {\r
-    transform: rotate(45deg);\r
-    border: 2px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuND6NzHYAAAEASURBVGhD7ZXRDcIwDEQ7AiMwQkdiQ0ZgBEbpCCWRiBRVob5zbaDSIeUD9WzfvSruNOknAiIgAiIgAiIgAiIgAiLwQwKXMvtezkx48NQQ7XFpNfIsZy1nAUN4anBHhLI3UgMgITw1hCVOOjKzF4LVc26catQUqnPaOFZmmbOeH5seVL1nsl3ydk+QuxJki2vzKURv/G/Nt6hWCHTVcuiC1df3St2Sr/9vwbPC2536DVjm0Y9dOFWk4am3kLXnrecIoDQNag7VpRkdNWZNsfr0MCND1p731KQG6Q1Z5kcfO7QmPcSjTJiJKTU4W0O0l1QEREAEREAEREAEREAEvkHgBRtRrTMkpctqAAAAAElFTkSuQmCC");\r
+.resizeable {\r
+    background-color: darkolivegreen;\r
+    border:1px solid blue;\r
+    margin: 10px;\r
 }\r
 \r
-.exclusiveGateway {\r
-    transform: rotate(45deg);\r
-    border: 2px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuND6NzHYAAAC4SURBVGhD7ZXRCcAgEEMdpSN0hI7WTTpKR+hIrZ9yIBi4SIUn+CGc0bwoVwoDAhCAAAQgAAEIQMBB4K6i7dwdhzg13yrezsN5mEMbAw6qiiYJKLQctSTgoKpokoBCS6mNHba3jgk8oTP39tk7drxY9tresbMvPP2vLG/grG95ZEaj1+C+TfmQztrpTyPbDAayiap6JKASy64ngWyiqh4JqMSy62O3/k2HzTaKHgQgAAEIQAACyxL4AOr3u2BKXQ3gAAAAAElFTkSuQmCC");\r
-}\r
index d4c59d6..1832944 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation\r
  */\r
 -->\r
-<div (dblclick)="showProperties($event)" class="node {{node.type}}" id="{{node.id}}"\r
-    (click)="onSelected()"\r
-    [class.active]="active"\r
-    [style.top]="node.position.top + 'px'"\r
-    [style.left]="node.position.left + 'px'">\r
-    <div class="name">\r
-        {{getDisplayName()}}\r
-    </div>\r
+<div (click)="onClick($event)" (mousedown)="onMousedown()" (dblclick)="showProperties($event)" class="node" id="{{node.id}}"\r
+(mouseover)="onMouseOver($event, $event.target.parentNode)" (mouseout)="onMouseOut($event, $event.target.parentNode)" [style.top]="node.position.top + 'px'"\r
+[style.left]="node.position.left + 'px'" [style.width]="node.position.width + 'px'" #nodeItem>\r
+\r
+<div class="name">{{node.name}}</div>\r
 \r
+<div *ngIf="canHaveChildren()" b4tResizable class="node-icon" [style.width]="node.position.width + 'px'" [style.height]="node.position.height + 'px'"\r
+    [class.active]="active">\r
+    <b4t-node *ngFor="let child of node.children" [node]="child" [rank]="rank + 10"></b4t-node>\r
     <div class="anchor anchors anchor-left">\r
         <span class="left">\r
             <i class="left-arrow1"></i>\r
             <i class="right-arrow2"></i>\r
         </span>\r
     </div>\r
-    <div class="anchor anchors anchor-top">\r
-        <span class="top">\r
-            <i class="top-arrow1"></i>\r
-            <i class="top-arrow2"></i>\r
+</div>\r
+\r
+<div *ngIf="!canHaveChildren()" class="node-icon" [class.active]="active">\r
+    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" [style.width]="node.position.width + 'px'" [style.height]="node.position.height + 'px'">\r
+        <g [ngSwitch]="node.type">\r
+            <g *ngSwitchCase="nodeType[nodeType.startEvent]">\r
+                <path class="st0" d="M15,2c7.2,0,13,5.8,13,13s-5.8,13-13,13S2,22.2,2,15S7.8,2,15,2 M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15\r
+                    s15-6.7,15-15S23.3,0,15,0L15,0z" />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.endEvent]">\r
+                <path class="st0" d="M15,4c6.1,0,11,4.9,11,11s-4.9,11-11,11S4,21.1,4,15S8.9,4,15,4 M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15\r
+                    s15-6.7,15-15S23.3,0,15,0L15,0z" />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.errorStartEvent]">\r
+                <path class="st0" d="M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15s15-6.7,15-15S23.3,0,15,0z M15,28C7.8,28,2,22.2,2,15S7.8,2,15,2\r
+                    s13,5.8,13,13S22.2,28,15,28z" />\r
+                <path class="st0" d="M19.7,12H17l2-5.5c0.1-0.3,0.1-0.5-0.1-0.7c-0.2-0.2-0.3-0.3-0.6-0.3H14c-0.3,0-0.6,0.2-0.8,0.5L9.7,16\r
+                    c-0.1,0.3-0.1,0.5,0.1,0.7c0.2,0.2,0.3,0.3,0.6,0.3l3.6,0.1l-1,6.7c-0.1,0.3,0.2,0.8,0.5,0.9c0.1,0,0.2,0,0.3,0\r
+                    c0.3,0,0.7-0.2,0.9-0.4l5.5-11.1c0.1-0.3,0.1-0.5,0-0.8C20.2,12.1,19.9,12,19.7,12z M14.6,22.3l1.2-5.9c0-0.3,0-0.4-0.2-0.6\r
+                    c-0.2-0.2-0.3-0.3-0.6-0.3h-3.5L14.5,7h2.6l-2,5.4C15,12.8,15,13,15.2,13.2c0.2,0.2,0.3,0.3,0.6,0.3h2.5L14.6,22.3z"\r
+                />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.errorEndEvent]">\r
+                <path class="st0" d="M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15s15-6.7,15-15S23.3,0,15,0z M15,26C8.9,26,4,21.1,4,15S8.9,4,15,4\r
+                    s11,4.9,11,11S21.1,26,15,26z" />\r
+                <path class="st0" d="M19.7,12.4H17l2-5.5c0.1-0.3,0.1-0.5-0.1-0.7c-0.2-0.2-0.3-0.3-0.6-0.3h-4.2c-0.3,0-0.6,0.2-0.8,0.5l-3.5,10\r
+                    c-0.1,0.3-0.1,0.5,0.1,0.7c0.2,0.2,0.3,0.3,0.6,0.3l3.6,0.1l-1,6.7c-0.1,0.3,0.2,0.8,0.5,0.9c0.1,0,0.2,0,0.3,0\r
+                    c0.3,0,0.7-0.2,0.9-0.4l5.5-11.1c0.1-0.3,0.1-0.5,0-0.8C20.2,12.6,20,12.4,19.7,12.4z" />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.toscaNodeManagementTask]">\r
+                <path class="st0" d="M24,29H6c-2.8,0-5-2.2-5-5V6c0-2.8,2.2-5,5-5h18c2.8,0,5,2.2,5,5v18C29,26.8,26.8,29,24,29z M6,3\r
+                    C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z" />\r
+                <path class="st0" d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z" />\r
+                <path class="st0" d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z" />\r
+                <path class="st0" d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z" />\r
+                <path class="st0" d="M24.7,15.1h-5c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1h1.5v5.7c0,0.6,0.4,1,1,1s1-0.4,1-1v-5.7h1.5c0.6,0,1-0.4,1-1\r
+                    C25.7,15.5,25.2,15.1,24.7,15.1z" />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.restTask]">\r
+                <path class="st0" d="M24,29H6c-2.8,0-5-2.2-5-5V6c0-2.8,2.2-5,5-5h18c2.8,0,5,2.2,5,5v18C29,26.8,26.8,29,24,29z M6,3\r
+                    C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z" />\r
+                <path class="st0" d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z" />\r
+                <path class="st0" d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z" />\r
+                <path class="st0" d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z" />\r
+                <path class="st0" d="M24.1,22.6l-1.6-2.7c0.9-0.4,1.5-1.2,1.5-2.2c0-1.4-1.2-2.5-2.8-2.5h-1.9c-0.2,0-0.4,0.1-0.6,0.2\r
+                    c-0.2,0.1-0.3,0.3-0.3,0.6v7c0,0.4,0.3,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8v-2.8h0.8l1.9,3.2c0.1,0.2,0.4,0.4,0.7,0.4\r
+                    c0.1,0,0.3,0,0.4-0.1C24.2,23.5,24.4,23,24.1,22.6z M20.1,16.8h1.2c0.6,0,1.2,0.4,1.2,0.9s-0.5,0.9-1.2,0.9h-1.2V16.8z"\r
+                />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.exclusiveGateway]">\r
+                <path class="st0" d="M16.4,15l3.2-3.2c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0L15,13.6l-3.2-3.2c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4\r
+                    l3.2,3.2l-3.2,3.2c-0.4,0.4-0.4,1,0,1.4s1,0.4,1.4,0l3.2-3.2l3.2,3.2c0.4,0.4,1,0.4,1.4,0s0.4-1,0-1.4L16.4,15z"\r
+                />\r
+                <path class="st0" d="M29.1,12.9l-12-12c-1.1-1.1-3.1-1.1-4.2,0l-12,12C0.3,13.4,0,14.2,0,15s0.3,1.6,0.9,2.1l12,12\r
+                    c0.6,0.6,1.3,0.9,2.1,0.9s1.6-0.3,2.1-0.9l12-12c0.6-0.6,0.9-1.3,0.9-2.1S29.7,13.4,29.1,12.9z M27.7,15.7l-12,12\r
+                    c-0.4,0.4-1,0.4-1.4,0l-12-12C2.1,15.5,2,15.3,2,15s0.1-0.5,0.3-0.7l12-12C14.5,2.1,14.7,2,15,2s0.5,0.1,0.7,0.3l12,12\r
+                    c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.parallelGateway]">\r
+                <path class="st0" d="M20.5,14H16V9.5c0-0.6-0.4-1-1-1s-1,0.4-1,1V14H9.5c-0.6,0-1,0.4-1,1s0.4,1,1,1H14v4.5c0,0.6,0.4,1,1,1\r
+                    s1-0.4,1-1V16h4.5c0.6,0,1-0.4,1-1S21.1,14,20.5,14z" />\r
+                <path class="st0" d="M29.1,12.9l-12-12c-1.1-1.1-3.1-1.1-4.2,0l-12,12C0.3,13.4,0,14.2,0,15s0.3,1.6,0.9,2.1l12,12\r
+                    c0.6,0.6,1.3,0.9,2.1,0.9s1.6-0.3,2.1-0.9l12-12c0.6-0.6,0.9-1.3,0.9-2.1S29.7,13.4,29.1,12.9z M27.7,15.7l-12,12\r
+                    c-0.4,0.4-1,0.4-1.4,0l-12-12C2.1,15.5,2,15.3,2,15s0.1-0.5,0.3-0.7l12-12C14.5,2.1,14.7,2,15,2s0.5,0.1,0.7,0.3l12,12\r
+                    c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.subProcess]">\r
+                <path class="st0" d="M24.5,1h-18c-2.8,0-5,2.2-5,5v18c0,2.8,2.2,5,5,5h18c2.8,0,5-2.2,5-5V6C29.5,3.2,27.2,1,24.5,1z M20.2,27h-9.4\r
+                    v-9.1c0-0.3,0.2-0.5,0.5-0.5h8.4c0.3,0,0.5,0.2,0.5,0.5V27z M27.5,24c0,1.7-1.3,3-3,3h-2.3v-9.1c0-1.4-1.1-2.5-2.5-2.5h-8.4\r
+                    c-1.4,0-2.5,1.1-2.5,2.5V27H6.5c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h18c1.7,0,3,1.3,3,3V24z" />\r
+                <path class="st0" d="M19,21.3h-2.5v-2.5c0-0.6-0.4-1-1-1c-0.6,0-1,0.4-1,1v2.5H12c-0.6,0-1,0.4-1,1s0.4,1,1,1h2.5v2.5\r
+                    c0,0.6,0.4,1,1,1c0.6,0,1-0.4,1-1v-2.5H19c0.6,0,1-0.4,1-1S19.5,21.3,19,21.3z" />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.intermediateCatchEvent]">\r
+                <path class="st0" d="M15,0C6.7,0,0,6.7,0,15c0,8.3,6.7,15,15,15c8.3,0,15-6.7,15-15C30,6.7,23.3,0,15,0z M16,27.9V26\r
+                    c0-0.6-0.4-1-1-1s-1,0.4-1,1v1.9C7.6,27.5,2.5,22.4,2.1,16H4c0.6,0,1-0.4,1-1s-0.4-1-1-1H2.1C2.5,7.6,7.6,2.5,14,2.1V4\r
+                    c0,0.6,0.4,1,1,1s1-0.4,1-1V2.1C22.4,2.5,27.5,7.6,27.9,14H26c-0.6,0-1,0.4-1,1s0.4,1,1,1h1.9C27.5,22.4,22.4,27.5,16,27.9z"\r
+                />\r
+                <path class="st0" d="M20,14h-3.6l2.5-6.6c0.2-0.5-0.1-1.1-0.6-1.3c-0.5-0.2-1.1,0.1-1.3,0.6l-3,8c-0.1,0.3-0.1,0.7,0.1,0.9\r
+                    c0.2,0.3,0.5,0.4,0.8,0.4h5c0.6,0,1-0.4,1-1S20.6,14,20,14z" />\r
+            </g>\r
+            <g *ngSwitchCase="nodeType[nodeType.scriptTask]">\r
+                <path class="st0" d="M24,1H6C3.2,1,1,3.2,1,6v18c0,2.8,2.2,5,5,5h18c2.8,0,5-2.2,5-5V6C29,3.2,26.8,1,24,1z M16.9,3.4\r
+                    c0.5,0,0.9,0.2,1.3,0.5c0.4,0.4,0.5,0.8,0.5,1.3c0,0.5-0.2,0.9-0.5,1.3L17.7,7l-5.3,5.3c-0.2-0.6-0.5-1.2-0.9-1.6\r
+                    c-0.4-0.4-1-0.8-1.6-0.9l5.8-5.8C16,3.6,16.4,3.4,16.9,3.4z M10.3,27H6c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h8.2l-7.4,7.4\r
+                    c-0.1,0.1-0.2,0.2-0.3,0.3c-0.7,0.7-1,1.6-1,2.5c0,0.9,0.4,1.8,1,2.5l5.2,5.2l-1.3,1.3c-0.7,0.7-1,1.6-1,2.5\r
+                    C9.3,25.5,9.7,26.4,10.3,27z M14.1,25.9c-0.4,0.4-0.8,0.5-1.3,0.5c-0.5,0-0.9-0.2-1.3-0.5c-0.4-0.4-0.5-0.8-0.5-1.3\r
+                    c0-0.5,0.2-0.9,0.5-1.3l1.3-1.3l0.5,0.5l0.8,0.8c0.4,0.4,0.5,0.8,0.5,1.3C14.6,25.1,14.5,25.5,14.1,25.9z M14.5,21.3l-6.8-6.8\r
+                    c-0.4-0.4-0.5-0.8-0.5-1.3c0-0.5,0.2-0.9,0.5-1.3c0.4-0.4,0.8-0.5,1.3-0.5c0.5,0,0.9,0.2,1.3,0.5c0.4,0.4,0.5,0.8,0.5,1.3\r
+                    c0,0.5-0.2,0.9-0.5,1.3l0.9,0.9c0.2,0.2,0.4,0.2,0.6,0l5.2-5.2l4.4,4.4l0.8,0.8c0.4,0.4,0.5,0.8,0.5,1.3c0,0.5-0.2,0.9-0.5,1.3v0\r
+                    l-5.8,5.8c-0.1-0.6-0.5-1.2-0.9-1.6L14.5,21.3z M27,24c0,1.7-1.3,3-3,3h-8.6l7.9-7.9c0.7-0.7,1-1.6,1-2.5c0-0.9-0.4-1.8-1-2.5\r
+                    l-0.8-0.8L18.1,9l1.3-1.3c0.7-0.7,1-1.6,1-2.5c0-0.8-0.3-1.6-0.8-2.2H24c1.7,0,3,1.3,3,3V24z" />\r
+                <path class="st0" d="M17.2,12.4c-0.3-0.3-0.8-0.3-1.1,0L12.6,16c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2\r
+                    l3.6-3.6C17.5,13.1,17.5,12.7,17.2,12.4z" />\r
+                <path class="st0" d="M18.9,14.2c-0.3-0.3-0.8-0.3-1.1,0l-3.6,3.6c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2\r
+                    c0.2,0,0.4-0.1,0.5-0.2l3.6-3.6C19.2,14.9,19.2,14.4,18.9,14.2z" />\r
+                <path class="st0" d="M17.1,20.6l3.6-3.6c0.3-0.3,0.3-0.8,0-1.1s-0.8-0.3-1.1,0L16,19.5c-0.3,0.3-0.3,0.8,0,1.1\r
+                    c0.1,0.1,0.3,0.2,0.5,0.2S17,20.7,17.1,20.6z" />\r
+            </g>\r
+        </g>\r
+    </svg>\r
+    <div class="anchor anchors anchor-left">\r
+        <span class="left">\r
+            <i class="left-arrow1"></i>\r
+            <i class="left-arrow2"></i>\r
         </span>\r
     </div>\r
-    <div class="anchor anchors anchor-bottom">\r
-        <span class="bottom">\r
-            <i class="bottom-arrow1"></i>\r
-            <i class="bottom-arrow2"></i>\r
+    <div class="anchor anchors anchor-right">\r
+        <span class="right">\r
+            <i class="right-arrow1"></i>\r
+            <i class="right-arrow2"></i>\r
         </span>\r
     </div>\r
 </div>\r
+</div>\r
index 5fe189d..e688e97 100644 (file)
@@ -9,16 +9,19 @@
  * Contributors:\r
  *     ZTE - initial API and implementation and/or initial documentation\r
  */\r
+import { AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild } from '@angular/core';\r
 \r
-import { Component, AfterViewInit, Input, OnDestroy } from '@angular/core';\r
-\r
+import { Subscription } from 'rxjs/Subscription';\r
+import { SubProcess } from '../../model/workflow/sub-process';\r
+import { WorkflowNode } from '../../model/workflow/workflow-node';\r
+import { BroadcastService } from '../../services/broadcast.service';\r
 import { JsPlumbService } from '../../services/jsplumb.service';\r
-import { BroadcastService } from "../../services/broadcast.service";\r
-import { WorkflowNode } from "../../model/workflow/workflow-node";\r
-import { Subscription } from "rxjs/Subscription";\r
+import { ModelService } from '../../services/model.service';\r
+import { NodeType } from '../../model/workflow/node-type.enum';\r
 \r
 /**\r
- * workflow node component\r
+ * node component represent a single workflow node.\r
+ * every node would be rendered on the container component\r
  */\r
 @Component({\r
     selector: 'b4t-node',\r
@@ -26,61 +29,85 @@ import { Subscription } from "rxjs/Subscription";
     templateUrl: 'node.component.html',\r
 })\r
 export class NodeComponent implements AfterViewInit, OnDestroy {\r
-\r
     @Input() public node: WorkflowNode;\r
-    @Input() public last: boolean;\r
+    @Input() public rank: number;\r
+    @ViewChild('nodeItem') nodeItem: ElementRef;\r
 \r
+    public nodeType = NodeType;\r
     public active = false;\r
-    private currentTypeSubscription: Subscription;\r
     private currentWorkflowSubscription: Subscription;\r
+    private isMoving = false;\r
 \r
-    constructor(private broadcastService: BroadcastService,\r
-        private jsPlumbService: JsPlumbService) {\r
-\r
+    constructor(private jsPlumbService: JsPlumbService,\r
+        private modelService: ModelService,\r
+        private broadcastService: BroadcastService) {\r
     }\r
 \r
-    ngAfterViewInit(): void {\r
-        if(this.last) {\r
-            this.jsPlumbService.initNode();\r
-            this.jsPlumbService.connectNodes();\r
-        }\r
+    public ngAfterViewInit() {\r
+        this.jsPlumbService.initJsPlumbInstance(this.node.parentId);\r
+        this.jsPlumbService.initNode(this.node);\r
 \r
-        this.currentTypeSubscription = this.broadcastService.currentType$.subscribe(type => {\r
-            if (type === 'SequenceFlow') {\r
-                this.active = false;\r
-            }\r
-        });\r
+        if (this.canHaveChildren()) {\r
+            this.jsPlumbService.nodeDroppable(this.node, this.rank);\r
+            this.jsPlumbService.connectChildrenNodes(this.node.id);\r
+        }\r
 \r
-        this.currentWorkflowSubscription = this.broadcastService.currentWorkflowNode$.subscribe(activeNode => {\r
-            if (activeNode.id === this.node.id) {\r
-                this.active = true;\r
-            } else {\r
-                this.active = false;\r
+        this.currentWorkflowSubscription = this.broadcastService.selectedElement$.subscribe(activeNodes => {\r
+            let active = false;\r
+            for (let index = 0; index < activeNodes.length; index++) {\r
+                let activeNode = activeNodes[index] as WorkflowNode;\r
+                if (activeNode.id === this.node.id) {\r
+                    active = true;\r
+                    break;\r
+                }\r
             }\r
+            this.active = active;\r
         });\r
     }\r
 \r
     public ngOnDestroy() {\r
-        this.currentTypeSubscription.unsubscribe();\r
         this.currentWorkflowSubscription.unsubscribe();\r
+        if (this.nodeItem.nativeElement.onmousemove) {\r
+            this.nodeItem.nativeElement.onmousemove = null;\r
+        }\r
     }\r
 \r
-    public showProperties() {\r
-        this.broadcastService.broadcast(this.broadcastService.nodeProperty, this.node);\r
-        this.broadcastService.broadcast(this.broadcastService.showProperty, true);\r
+    public onMousedown() {\r
+        let currentThis = this;\r
+        this.nodeItem.nativeElement.onmousemove = function () {\r
+            currentThis.isMoving = true;\r
+        };\r
     }\r
 \r
-    public getDisplayName(): string {\r
-        if (this.node.type === 'restTask' || this.node.type === 'toscaTask') {\r
-            return this.node.name;\r
-        } else {\r
-            return '     ';\r
+    public onClick(event) {\r
+        if (this.nodeItem.nativeElement.onmousemove) {\r
+            this.nodeItem.nativeElement.onmousemove = null;\r
+        }\r
+        if (this.isMoving && this.active) {\r
+            this.isMoving = false;\r
+            return;\r
         }\r
+        event.stopPropagation();\r
+        this.broadcastService.broadcast(this.broadcastService.showProperty, null);\r
+        this.broadcastService.broadcast(this.broadcastService.selectedElement, [this.node]);\r
+    }\r
+\r
+    public canHaveChildren(): boolean {\r
+        return this.node.type === 'subProcess';\r
     }\r
 \r
-    public onSelected() {\r
-        this.broadcastService.broadcast(this.broadcastService.currentWorkflowNode, this.node);\r
-        this.broadcastService.broadcast(this.broadcastService.currentType, 'WorkflowNode');\r
+    public onMouseOut(event, target) {\r
+        event.stopPropagation();\r
+        target.classList.remove('hover');\r
     }\r
 \r
+    public onMouseOver(event, target) {\r
+        event.stopPropagation();\r
+        target.classList.add('hover');\r
+    }\r
+\r
+    public showProperties(event) {\r
+        event.stopPropagation();\r
+        this.broadcastService.broadcast(this.broadcastService.showProperty, this.node);\r
+    }\r
 }\r
index 9271dac..77da46b 100644 (file)
@@ -22,6 +22,7 @@ import { SwaggerTreeConverterService } from '../../services/swagger-tree-convert
 import { WorkflowUtil } from '../../util/workflow-util';
 import { Swagger } from "../../model/swagger";
 import { WorkflowConfigService } from "../../services/workflow-config.service";
+import { RestService } from '../../services/rest.service';
 
 /**
  * parameter tree presents parameter of task node's input and output parameters.
@@ -37,8 +38,9 @@ export class ParameterTreeComponent implements OnChanges {
     @Input() public defaultValueSource: string;
     @Input() public valueSource: ValueSource[];
     @Input() public planItems: PlanTreeviewItem[];
+    @Input() public restConfigId: string;
 
-    constructor(private restService: WorkflowConfigService, private swaggerTreeConverterService: SwaggerTreeConverterService) { }
+    constructor(private restService: RestService, private swaggerTreeConverterService: SwaggerTreeConverterService) { }
 
     public ngOnChanges(changes: SimpleChanges) {
         // const changeParameters = changes['parameters'];
@@ -81,7 +83,7 @@ export class ParameterTreeComponent implements OnChanges {
     }
 
     private getSwagger(): Swagger {
-      return this.restService.getSwaggerInfo(this.task.serviceName, this.task.serviceVersion);
+        return this.restService.getSwaggerInfo(this.restConfigId);
     }
 
     public getKeyParameter(node: any) {
index 2870a4b..19d0dce 100644 (file)
 
 <div class="wm-properties-wrapper" *ngIf="show">
     <div class="form-group row">
-        <div *ngIf="!titleEditing" class="view col-md-10" (dblclick)="titleEditing = !titleEditing">
-            <h4>{{node.name}}</h4>
-        </div>
-        <div class="col-md-10" *ngIf="titleEditing">
-            <input class="form-control" (blur)="nodeNameChanged()" type="text" [(ngModel)]="node.name"/>
-        </div>
-
+        <b4t-editable-property class="col-md-10" [(name)]="node.name"></b4t-editable-property>
         <div class="col-md-2">
-            <button (click)="deleteNode()" type="button" class="btn btn-danger">
+            <button (click)="deleteNode()" type="button" class="btn white">
                 <i class="fa fa-trash" style="margin-right: 5px;"></i>
             </button>
         </div>
-
     </div>
     <hr>
 
index 2091d83..d3a6a41 100644 (file)
@@ -35,8 +35,8 @@ export class PropertiesComponent implements AfterViewInit {
     public planItems: PlanTreeviewItem[];
 
     constructor(private broadcastService: BroadcastService,
-                private jsPlumnService: JsPlumbService,
-                private processService: ModelService) {
+                private jsPlumbService: JsPlumbService,
+                private modelService: ModelService) {
 
     }
 
@@ -44,19 +44,14 @@ export class PropertiesComponent implements AfterViewInit {
         this.broadcastService.showProperty$.subscribe(show => this.show = show);
         this.broadcastService.nodeProperty$.subscribe(node => {
             this.node = node;
-            this.planItems = this.processService.getPlanParameters(this.node.id);
+            this.planItems = this.modelService.getPlanParameters(this.node.id);
         });
     }
 
-    public nodeNameChanged() {
-        this.titleEditing = !this.titleEditing;
-        this.jsPlumnService.jsplumbInstance.repaintEverything();
-    }
-
     public deleteNode() {
         this.show = false;
-
-        this.jsPlumnService.remove(this.node.id);
-        this.processService.deleteNode(this.node.id);
+        const parentId = this.jsPlumbService.getParentNodeId(this.node.id);
+        this.jsPlumbService.remove(this.node);
+        this.modelService.deleteNode(parentId, this.node.id);
     }
 }
index 7f8bbf4..8e8cc94 100644 (file)
@@ -21,6 +21,7 @@ import { ValueSource } from "../../../../model/value-source.enum";
 import { SwaggerTreeConverterService } from "../../../../services/swagger-tree-converter.service";
 import { PlanTreeviewItem } from "../../../../model/plan-treeview-item";
 import { WorkflowConfigService } from "../../../../services/workflow-config.service";
+import { RestService } from '../../../../services/rest.service';
 
 /**
  * property component presents information of a workflow node.
@@ -44,7 +45,7 @@ export class RestTaskParametersComponent implements OnInit {
     private index = 1;
 
     constructor(private broadcastService: BroadcastService,
-        private workflowConfigService: WorkflowConfigService,
+        private restService: RestService,
         private swaggerTreeConverterService: SwaggerTreeConverterService) {
     }
 
@@ -62,7 +63,7 @@ export class RestTaskParametersComponent implements OnInit {
         this.task.parameters.forEach(param => {
             if (param.position === 'body') {
                 const requestTreeNode = this.swaggerTreeConverterService
-                    .schema2TreeNode(this.workflowConfigService.getSwaggerInfo(this.task.serviceName, this.task.serviceVersion), 'Request Param', param.schema, param.value);
+                    .schema2TreeNode(this.restService.getSwaggerInfo(this.task.restConfigId), 'Request Param', param.schema, param.value);
                 param.value = requestTreeNode.value;
                 param.value = param.schema.value;
                 this.bodyParameter.push(requestTreeNode);
index d0c92df..eb1c81b 100644 (file)
@@ -9,91 +9,61 @@
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  *******************************************************************************/
-import { AfterViewInit, Component, Input, OnInit } from '@angular/core';
+import { Component, Input, OnInit } from '@angular/core';
 import { Subscription } from 'rxjs/Subscription';
 
+import { PlanTreeviewItem } from '../../../model/plan-treeview-item';
 import { Swagger, SwaggerMethod, SwaggerParameter, SwaggerResponse } from '../../../model/swagger';
 import { ValueSource } from '../../../model/value-source.enum';
 import { ValueType } from '../../../model/value-type.enum';
+import { RestParameter } from '../../../model/workflow/rest-parameter';
 import { RestTask } from '../../../model/workflow/rest-task';
 import { BroadcastService } from '../../../services/broadcast.service';
-import { WorkflowConfigService } from '../../../services/workflow-config.service';
-import { Microservice } from "../../../model/workflow/microservice";
-import { WorkflowUtil } from "../../../util/workflow-util";
-import { RestParameter } from "../../../model/workflow/rest-parameter";
-import { PlanTreeviewItem } from "../../../model/plan-treeview-item";
+import { RestService } from '../../../services/rest.service';
+import { WorkflowUtil } from '../../../util/workflow-util';
 
 @Component({
     selector: 'b4t-rest-task',
     templateUrl: 'rest-task.component.html',
 })
-export class RestTaskComponent implements AfterViewInit, OnInit {
+export class RestTaskComponent implements OnInit {
     @Input() public node: RestTask;
     @Input() public planItems: PlanTreeviewItem[];
-
     public swaggerJson: any = {};
     public restInterfaces: any[];
     public restOperations: any = [];
-    public microservices: Microservice[];
-    public selectedMicroservice: Microservice;
     private swagger: Swagger;
 
-    constructor(private broadcastService: BroadcastService,
-        private configService: WorkflowConfigService) { }
-
-    ngOnInit(): void {
-        this.microservices = this.configService.getMicroservices();
-        this.selectedMicroservice = this.microservices.find(service =>
-            (this.node.serviceName === service.name && this.node.serviceVersion === service.version));
-    }
-    public ngAfterViewInit() {
-        setTimeout(() => {
-            this.loadInterfaces();
-            this.notifyTaskChanged();
-        }, 0);
-    }
-
-    private notifyTaskChanged() {
-        this.broadcastService.broadcast(this.broadcastService.nodeTaskChange, this.node);
-    }
+    constructor(private broadcastService: BroadcastService, public restService: RestService) { }
 
-    public getText4Microservice(microservice: Microservice): string {
-        return `${microservice.name} [${microservice.version}] `;
+    public ngOnInit() {
+        this.loadInterfaces();
     }
 
-    public serviceChanged(service: Microservice) {
-        this.selectedMicroservice = service;
-        this.node.serviceName = service.name;
-        this.node.serviceVersion = service.version;
-        this.urlChanged('');
+    public serviceChanged(configId: string) {
+        this.node.restConfigId = configId;
+        this.pathChanged('');
         this.loadInterfaces();
     }
 
-    public urlChanged(url: string) {
-        this.node.url = url;
-
+    public pathChanged(path: string) {
+        this.node.path = path;
         this.node.consumes = [];
         this.node.produces = [];
         this.methodChanged('');
-
         this.loadOperations();
     }
 
     public methodChanged(method: string) {
         this.node.method = method;
-
         this.node.parameters = [];
         this.node.responses = [];
-
         this.updateMethodInfo();
-
-        this.notifyTaskChanged();
     }
 
-
     private loadInterfaces() {
-        if (this.node.serviceName && this.node.serviceVersion) {
-            this.swagger = this.configService.getSwaggerInfo(this.node.serviceName, this.node.serviceVersion);
+        if (this.node.restConfigId) {
+            this.swagger = this.restService.getSwaggerInfo(this.node.restConfigId);
 
             if (this.swagger) {
                 this.restInterfaces = [];
@@ -101,15 +71,13 @@ export class RestTaskComponent implements AfterViewInit, OnInit {
                     this.restInterfaces.push(key);
                 }
                 this.loadOperations();
-            } else {
-                // TODO error handler
             }
         }
     }
 
     private loadOperations() {
-        if (this.node.url) {
-            const swaggerPath: any = this.swagger.paths[this.node.url];
+        if (this.node.path) {
+            const swaggerPath: any = this.swagger.paths[this.node.path];
 
             this.restOperations = [];
             for (const key of Object.keys(swaggerPath)) {
@@ -120,34 +88,23 @@ export class RestTaskComponent implements AfterViewInit, OnInit {
 
     private updateMethodInfo() {
         if (this.node.method) {
-            const path: any = this.swagger.paths[this.node.url];
+            const path: any = this.swagger.paths[this.node.path];
             const method: SwaggerMethod = path[this.node.method];
 
             this.node.consumes = WorkflowUtil.deepClone(method.consumes);
             this.node.produces = WorkflowUtil.deepClone(method.produces);
 
-            // request parameters
+            let tempParameters: RestParameter[] = [];
             method.parameters.forEach(param => {
                 const nodeParam = new RestParameter(param.name, '', ValueSource[ValueSource.String],
-                    param.type, param.position, param.schema);
-                this.node.parameters.push(nodeParam);
+                    ValueType[ValueType.String], param.position, param.schema, param.required);
+                tempParameters.push(WorkflowUtil.deepClone(nodeParam));
             });
+            this.node.parameters = tempParameters;
 
-            // response parameters
-            const responseParams = this.getResponseParameters(method.responses);
+            const responseParams = this.restService.getResponseParameters(
+                this.swagger, this.node.path, this.node.method);
             this.node.responses = responseParams.map(param => WorkflowUtil.deepClone(param));
         }
     }
-
-    private getResponseParameters(responses: any) {
-        let response: SwaggerResponse = null;
-
-        for (const key of Object.keys(responses)) {
-            if (key.startsWith('20')) {
-                response = responses[key];
-            }
-        }
-
-        return [response];
-    }
 }
index c4a70ec..b114d0a 100644 (file)
@@ -51,7 +51,7 @@ export class SequenceFlowComponent implements AfterViewInit {
     public delete() {
         this.show = false;
 
-        this.processService.deleteSequenceFlow(this.sequenceFlow.sourceRef, this.sequenceFlow.targetRef);
+        this.processService.deleteConnection(this.sequenceFlow.sourceRef, this.sequenceFlow.targetRef);
         this.jsPlumbService.deleteConnect(this.sequenceFlow.sourceRef, this.sequenceFlow.targetRef);
     }
 }
index 3edffd6..1d11953 100644 (file)
  * Contributors:\r
  *     ZTE - initial API and implementation and/or initial documentation\r
  */\r
-\r
- .toolbar{\r
-    padding: 20px 10px;\r
-}\r
-\r
-.row{\r
-    margin: 0;\r
-}\r
-\r
-button {\r
-    min-width: 40px;\r
-    width: 60px;\r
-    height: 60px;\r
-    transition: all 0s;\r
-    margin: 10px;\r
-    padding: 0;\r
-}\r
-\r
-button div{\r
-    left: 0;\r
-    right: 0;\r
-    margin: auto;\r
-    width: 40px;\r
-    height: 40px;\r
-}\r
-\r
-button span{\r
-    padding: 0;\r
-    font-size: 10px;\r
-    letter-spacing: 0px;\r
-    color: black;\r
+ .toolbar-head{\r
+    color:#404040;\r
+    font-size: 14px;\r
 }\r
 \r
-.subProcess {\r
-    border-radius: 8px;\r
-    border: 2px solid rgb(0, 0, 0);\r
-    font-size: 10px;\r
+.toolbar-head:hover{\r
+    cursor: pointer;\r
 }\r
 \r
-.parallelGateway {\r
-    transform: rotate(45deg);\r
-    border: 2px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px !important;\r
-    width: 30px !important;\r
-    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuND6NzHYAAAEASURBVGhD7ZXRDcIwDEQ7AiMwQkdiQ0ZgBEbpCCWRiBRVob5zbaDSIeUD9WzfvSruNOknAiIgAiIgAiIgAiIgAiLwQwKXMvtezkx48NQQ7XFpNfIsZy1nAUN4anBHhLI3UgMgITw1hCVOOjKzF4LVc26catQUqnPaOFZmmbOeH5seVL1nsl3ydk+QuxJki2vzKURv/G/Nt6hWCHTVcuiC1df3St2Sr/9vwbPC2536DVjm0Y9dOFWk4am3kLXnrecIoDQNag7VpRkdNWZNsfr0MCND1p731KQG6Q1Z5kcfO7QmPcSjTJiJKTU4W0O0l1QEREAEREAEREAEREAEvkHgBRtRrTMkpctqAAAAAElFTkSuQmCC");\r
+.fold-icon{\r
+    width: 15px;\r
+    font-size: 8px;\r
+    color: #00abff;\r
 }\r
 \r
-.exclusiveGateway {\r
-    transform: rotate(45deg);\r
-    border: 2px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px !important;\r
-    width: 30px !important;\r
-    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuND6NzHYAAAC4SURBVGhD7ZXRCcAgEEMdpSN0hI7WTTpKR+hIrZ9yIBi4SIUn+CGc0bwoVwoDAhCAAAQgAAEIQMBB4K6i7dwdhzg13yrezsN5mEMbAw6qiiYJKLQctSTgoKpokoBCS6mNHba3jgk8oTP39tk7drxY9tresbMvPP2vLG/grG95ZEaj1+C+TfmQztrpTyPbDAayiap6JKASy64ngWyiqh4JqMSy62O3/k2HzTaKHgQgAAEIQAACyxL4AOr3u2BKXQ3gAAAAAElFTkSuQmCC");\r
+.item{\r
+    width: 50px;\r
+    height: 50px;\r
+    text-align: center;\r
+    float: left;\r
+    margin-left: 6px;\r
+    margin-bottom: 10px;\r
 }\r
 \r
-.startEvent {\r
-    border-radius: 30px;\r
-    border: 1px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    /*background-image: url("data:image/png;base64,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");*/\r
+.item:hover{\r
+    cursor: pointer;\r
 }\r
 \r
-.endEvent {\r
-    border-radius: 30px;\r
-    border: 2px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    /*background-image: url("data:image/png;base64,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");*/\r
+.item svg{\r
+    width:24px;\r
+    height:24px;\r
+    margin: 4px 13px;\r
+    display: block;\r
+    /* fill: #A9B2BA; */\r
+    fill: #00ABFF;\r
 }\r
 \r
-.intermediateCatchEvent {\r
-    border-radius: 30px;\r
-    border: 1px solid rgb(0, 0, 0);\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    background-image: url("data:image/svg+xml;utf8,<?xml version='1.0' encoding='UTF-8' standalone='no'?><svg xmlns='http://www.w3.org/2000/svg' xmlns:oryx='http://www.b3mn.org/oryx' viewBox='1 1 30 30' width='28' height='28' style='fill:transparent' version='1.0'> <defs></defs> <oryx:magnets> <oryx:magnet oryx:cx='16' oryx:cy='16' oryx:default='yes' /> </oryx:magnets> <oryx:docker oryx:cx='16' oryx:cy='16' /> <g pointer-events='fill'> <defs> <radialGradient id='background' cx='10%' cy='10%' r='100%' fx='10%' fy='10%'> <stop offset='0%' stop-color='#ffffff' stop-opacity='1'/> <stop id='fill_el' offset='100%' stop-color='#ffffff' stop-opacity='1'/> </radialGradient> </defs> <circle id='bg_frame' cx='16' cy='16' r='15' stroke='black' stroke-width='1' style='stroke-dasharray: 5.5, 3' />  <circle id='frame2_non_interrupting' cx='16' cy='16' r='12' stroke='black' fill='none' stroke-width='1' style='stroke-dasharray: 4.5, 3' /><circle id='frame' cx='16' cy='16' r='15' stroke='black' fill='none' stroke-width='1'/><circle id='frame2' cx='16' cy='16' r='12' stroke='black' fill='none' stroke-width='1'/><circle id='circle' cx='16' cy='16' r='10' stroke='black' fill='none' stroke-width='1'/> <path id='path1' d='M 16 6 L 16 9 M 21 7 L 19.5 10 M 25 11 L 22 12.5 M 26 16 L 23 16 M 25 21 L 22 19.5 M 21 25 L 19.5 22 M 16 26 L 16 23 M 11 25 L 12.5 22 M 7 21 L 10 19.5 M 6 16 L 9 16 M 7 11 L 10 12.5 M 11 7 L 12.5 10 M 18 9 L 16 16 L 20 16' fill='none' stroke='black' /> <text font-size='11' id='text_name' x='16' y='33' oryx:align='top center' stroke='black'></text></g></svg>");\r
+.item span{\r
+    font-size: 12px;\r
+    color: #595959;\r
+    display: block;\r
 }\r
 \r
-\r
-.scriptTask {\r
-    background-size: cover;\r
-    height: 30px;\r
-    width: 30px;\r
-    background-image: url("data:image/svg+xml;utf8,<?xml version='1.0' encoding='UTF-8' standalone='no'?> <svg    xmlns='http://www.w3.org/2000/svg'    xmlns:svg='http://www.w3.org/2000/svg'    xmlns:oryx='http://www.b3mn.org/oryx'    version='1.0' width='100%' height='100%'>           <g id='scriptTask' transform='scale(1, 1) translate(8,8)'>              <path oryx:anchors='top left' id='paper' style='opacity:1;fill:none;stroke:#000000'             d='M6.402,0.5h14.5c0,0-5.833,2.833-5.833,5.583s4.417,6,4.417,9.167                      s-4.167,5.083-4.167,5.083H0.235c0,0,5-2.667,5-5s-4.583-6.75-4.583-9.25S6.402,0.5,6.402,0.5z'/>          <path oryx:anchors='top left' id='line1' style='opacity:1;fill:none;stroke:#000000;stroke-width:1.5' d='M 3.5 4.5 L 13.5 4.5' />                <path oryx:anchors='top left' id='line2' style='opacity:1;fill:none;stroke:#000000;stroke-width:1.5' d='M 3.8 8.5 L 13.8 8.5' />                <path oryx:anchors='top left'  id='line3' style='opacity:1;fill:none;stroke:#000000;stroke-width:1.5' d='M 6.3 12.5 L 16.3 12.5' />             <path oryx:anchors='top left' id='line4' style='opacity:1;fill:none;stroke:#000000;stroke-width:1.5' d='M 6.5 16.5 L 16.5 16.5' />      </g> </svg> ");\r
+.getway{\r
+    padding-top: 5px;\r
 }\r
 \r
-.toscaTask {\r
-    border-radius: 8px;\r
-    border: 2px solid rgb(0, 0, 0);\r
-    font-size: 10px;\r
-}\r
-\r
-.restTask {\r
-    border-radius: 8px;\r
-    border: 2px solid rgb(0, 0, 0);\r
-    font-size: 10px;\r
+.getway div{\r
+    width: 30px !important;\r
+    height: 30px !important;\r
 }\r
index bb52644..382e195 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation\r
  */\r
 -->\r
-<div class="toolbar">\r
-    <div class="row">\r
-        <button *ngFor="let nodeType of nodeTypes" type="button" [attr.nodeType]="nodeType"\r
-            class="btn btn-secondary item ui-draggable">\r
-            <div class="{{nodeType}}">\r
-            </div>\r
-            <span>{{getNameByType(nodeType)}}</span>\r
-        </button>\r
-    </div>\r
-</div>\r
+<accordion>\r
+    <accordion-group [isOpen]="true" #event>\r
+        <div accordion-heading class="toolbar-head">\r
+            <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': event?.isOpen, 'fa-chevron-right': !event?.isOpen}"></i>\r
+            <i class="fa fa-th-list"></i>\r
+            <span>EVENT</span>\r
+        </div>\r
+        <div nodeType="startEvent" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M15,2c7.2,0,13,5.8,13,13s-5.8,13-13,13S2,22.2,2,15S7.8,2,15,2 M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15\r
+                    s15-6.7,15-15S23.3,0,15,0L15,0z" />\r
+                </g>\r
+            </svg>\r
+            <span>Start</span>\r
+        </div>\r
+        <div nodeType="endEvent" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M15,4c6.1,0,11,4.9,11,11s-4.9,11-11,11S4,21.1,4,15S8.9,4,15,4 M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15\r
+                s15-6.7,15-15S23.3,0,15,0L15,0z" />\r
+                </g>\r
+            </svg>\r
+            <span>End</span>\r
+        </div>\r
+        <div nodeType="intermediateCatchEvent" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M15,0C6.7,0,0,6.7,0,15c0,8.3,6.7,15,15,15c8.3,0,15-6.7,15-15C30,6.7,23.3,0,15,0z M16,27.9V26\r
+                        c0-0.6-0.4-1-1-1s-1,0.4-1,1v1.9C7.6,27.5,2.5,22.4,2.1,16H4c0.6,0,1-0.4,1-1s-0.4-1-1-1H2.1C2.5,7.6,7.6,2.5,14,2.1V4\r
+                        c0,0.6,0.4,1,1,1s1-0.4,1-1V2.1C22.4,2.5,27.5,7.6,27.9,14H26c-0.6,0-1,0.4-1,1s0.4,1,1,1h1.9C27.5,22.4,22.4,27.5,16,27.9z"\r
+                    />\r
+                    <path class="st0" d="M20,14h-3.6l2.5-6.6c0.2-0.5-0.1-1.1-0.6-1.3c-0.5-0.2-1.1,0.1-1.3,0.6l-3,8c-0.1,0.3-0.1,0.7,0.1,0.9\r
+                        c0.2,0.3,0.5,0.4,0.8,0.4h5c0.6,0,1-0.4,1-1S20.6,14,20,14z" />\r
+                </g>\r
+            </svg>\r
+            <span>Timer</span>\r
+        </div>\r
+        <!--\r
+        <div nodeType="errorStartEvent" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15s15-6.7,15-15S23.3,0,15,0z M15,28C7.8,28,2,22.2,2,15S7.8,2,15,2\r
+                        s13,5.8,13,13S22.2,28,15,28z" />\r
+                    <path class="st0" d="M19.7,12H17l2-5.5c0.1-0.3,0.1-0.5-0.1-0.7c-0.2-0.2-0.3-0.3-0.6-0.3H14c-0.3,0-0.6,0.2-0.8,0.5L9.7,16\r
+                        c-0.1,0.3-0.1,0.5,0.1,0.7c0.2,0.2,0.3,0.3,0.6,0.3l3.6,0.1l-1,6.7c-0.1,0.3,0.2,0.8,0.5,0.9c0.1,0,0.2,0,0.3,0\r
+                        c0.3,0,0.7-0.2,0.9-0.4l5.5-11.1c0.1-0.3,0.1-0.5,0-0.8C20.2,12.1,19.9,12,19.7,12z M14.6,22.3l1.2-5.9c0-0.3,0-0.4-0.2-0.6\r
+                        c-0.2-0.2-0.3-0.3-0.6-0.3h-3.5L14.5,7h2.6l-2,5.4C15,12.8,15,13,15.2,13.2c0.2,0.2,0.3,0.3,0.6,0.3h2.5L14.6,22.3z"\r
+                    />\r
+                </g>\r
+            </svg>\r
+            <span>{{ 'WORKFLOW.ERROR_START_EVENT' | translate }}</span>\r
+        </div>\r
+        <div nodeType="errorEndEvent" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M15,0C6.7,0,0,6.7,0,15s6.7,15,15,15s15-6.7,15-15S23.3,0,15,0z M15,26C8.9,26,4,21.1,4,15S8.9,4,15,4\r
+                        s11,4.9,11,11S21.1,26,15,26z" />\r
+                    <path class="st0" d="M19.7,12.4H17l2-5.5c0.1-0.3,0.1-0.5-0.1-0.7c-0.2-0.2-0.3-0.3-0.6-0.3h-4.2c-0.3,0-0.6,0.2-0.8,0.5l-3.5,10\r
+                        c-0.1,0.3-0.1,0.5,0.1,0.7c0.2,0.2,0.3,0.3,0.6,0.3l3.6,0.1l-1,6.7c-0.1,0.3,0.2,0.8,0.5,0.9c0.1,0,0.2,0,0.3,0\r
+                        c0.3,0,0.7-0.2,0.9-0.4l5.5-11.1c0.1-0.3,0.1-0.5,0-0.8C20.2,12.6,20,12.4,19.7,12.4z" />\r
+                </g>\r
+            </svg>\r
+            <span>{{ 'WORKFLOW.ERROR_END_EVENT' | translate }}</span>\r
+        </div>\r
+      -->\r
+    </accordion-group>\r
+    <accordion-group [isOpen]="true" #task>\r
+        <div accordion-heading class="toolbar-head">\r
+            <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': task?.isOpen, 'fa-chevron-right': !task?.isOpen}"></i>\r
+            <i class="fa fa-th-list"></i>\r
+            <span>Task</span>\r
+        </div>\r
+        <div *ngIf="!isCatalog" nodeType="toscaNodeManagementTask" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M24,29H6c-2.8,0-5-2.2-5-5V6c0-2.8,2.2-5,5-5h18c2.8,0,5,2.2,5,5v18C29,26.8,26.8,29,24,29z M6,3\r
+                        C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z" />\r
+                    <path class="st0" d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z" />\r
+                    <path class="st0" d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z" />\r
+                    <path class="st0" d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z" />\r
+                    <path class="st0" d="M24.7,15.1h-5c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1h1.5v5.7c0,0.6,0.4,1,1,1s1-0.4,1-1v-5.7h1.5c0.6,0,1-0.4,1-1\r
+                        C25.7,15.5,25.2,15.1,24.7,15.1z" />\r
+                </g>\r
+            </svg>\r
+            <span>TOSCA</span>\r
+        </div>\r
+        <div *ngIf="isCatalog" nodeType="restTask" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M24,29H6c-2.8,0-5-2.2-5-5V6c0-2.8,2.2-5,5-5h18c2.8,0,5,2.2,5,5v18C29,26.8,26.8,29,24,29z M6,3\r
+                        C4.3,3,3,4.3,3,6v18c0,1.7,1.3,3,3,3h18c1.7,0,3-1.3,3-3V6c0-1.7-1.3-3-3-3H6z" />\r
+                    <path class="st0" d="M7.6,14.5h7.5c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,14.5,7.6,14.5z" />\r
+                    <path class="st0" d="M7.6,18.7h3.7c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,18.7,7.6,18.7z" />\r
+                    <path class="st0" d="M7.6,10.4H19c0.5,0,0.8-0.4,0.8-1s-0.3-1-0.8-1H7.6c-0.5,0-0.8,0.4-0.8,1S7.1,10.4,7.6,10.4z" />\r
+                    <path class="st0" d="M24.1,22.6l-1.6-2.7c0.9-0.4,1.5-1.2,1.5-2.2c0-1.4-1.2-2.5-2.8-2.5h-1.9c-0.2,0-0.4,0.1-0.6,0.2\r
+                        c-0.2,0.1-0.3,0.3-0.3,0.6v7c0,0.4,0.3,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8v-2.8h0.8l1.9,3.2c0.1,0.2,0.4,0.4,0.7,0.4\r
+                        c0.1,0,0.3,0,0.4-0.1C24.2,23.5,24.4,23,24.1,22.6z M20.1,16.8h1.2c0.6,0,1.2,0.4,1.2,0.9s-0.5,0.9-1.2,0.9h-1.2V16.8z"\r
+                    />\r
+                </g>\r
+            </svg>\r
+            <span>Rest</span>\r
+        </div>\r
+        <div nodeType="scriptTask" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M24,1H6C3.2,1,1,3.2,1,6v18c0,2.8,2.2,5,5,5h18c2.8,0,5-2.2,5-5V6C29,3.2,26.8,1,24,1z M16.9,3.4\r
+                        c0.5,0,0.9,0.2,1.3,0.5c0.4,0.4,0.5,0.8,0.5,1.3c0,0.5-0.2,0.9-0.5,1.3L17.7,7l-5.3,5.3c-0.2-0.6-0.5-1.2-0.9-1.6\r
+                        c-0.4-0.4-1-0.8-1.6-0.9l5.8-5.8C16,3.6,16.4,3.4,16.9,3.4z M10.3,27H6c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h8.2l-7.4,7.4\r
+                        c-0.1,0.1-0.2,0.2-0.3,0.3c-0.7,0.7-1,1.6-1,2.5c0,0.9,0.4,1.8,1,2.5l5.2,5.2l-1.3,1.3c-0.7,0.7-1,1.6-1,2.5\r
+                        C9.3,25.5,9.7,26.4,10.3,27z M14.1,25.9c-0.4,0.4-0.8,0.5-1.3,0.5c-0.5,0-0.9-0.2-1.3-0.5c-0.4-0.4-0.5-0.8-0.5-1.3\r
+                        c0-0.5,0.2-0.9,0.5-1.3l1.3-1.3l0.5,0.5l0.8,0.8c0.4,0.4,0.5,0.8,0.5,1.3C14.6,25.1,14.5,25.5,14.1,25.9z M14.5,21.3l-6.8-6.8\r
+                        c-0.4-0.4-0.5-0.8-0.5-1.3c0-0.5,0.2-0.9,0.5-1.3c0.4-0.4,0.8-0.5,1.3-0.5c0.5,0,0.9,0.2,1.3,0.5c0.4,0.4,0.5,0.8,0.5,1.3\r
+                        c0,0.5-0.2,0.9-0.5,1.3l0.9,0.9c0.2,0.2,0.4,0.2,0.6,0l5.2-5.2l4.4,4.4l0.8,0.8c0.4,0.4,0.5,0.8,0.5,1.3c0,0.5-0.2,0.9-0.5,1.3v0\r
+                        l-5.8,5.8c-0.1-0.6-0.5-1.2-0.9-1.6L14.5,21.3z M27,24c0,1.7-1.3,3-3,3h-8.6l7.9-7.9c0.7-0.7,1-1.6,1-2.5c0-0.9-0.4-1.8-1-2.5\r
+                        l-0.8-0.8L18.1,9l1.3-1.3c0.7-0.7,1-1.6,1-2.5c0-0.8-0.3-1.6-0.8-2.2H24c1.7,0,3,1.3,3,3V24z" />\r
+                    <path class="st0" d="M17.2,12.4c-0.3-0.3-0.8-0.3-1.1,0L12.6,16c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2\r
+                        l3.6-3.6C17.5,13.1,17.5,12.7,17.2,12.4z" />\r
+                    <path class="st0" d="M18.9,14.2c-0.3-0.3-0.8-0.3-1.1,0l-3.6,3.6c-0.3,0.3-0.3,0.8,0,1.1c0.1,0.1,0.3,0.2,0.5,0.2\r
+                        c0.2,0,0.4-0.1,0.5-0.2l3.6-3.6C19.2,14.9,19.2,14.4,18.9,14.2z" />\r
+                    <path class="st0" d="M17.1,20.6l3.6-3.6c0.3-0.3,0.3-0.8,0-1.1s-0.8-0.3-1.1,0L16,19.5c-0.3,0.3-0.3,0.8,0,1.1\r
+                        c0.1,0.1,0.3,0.2,0.5,0.2S17,20.7,17.1,20.6z" />\r
+                </g>\r
+            </svg>\r
+            <span>Script</span>\r
+        </div>\r
+    </accordion-group>\r
+    <accordion-group [isOpen]="true" #getway>\r
+        <div accordion-heading class="toolbar-head">\r
+            <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': getway?.isOpen, 'fa-chevron-right': !getway?.isOpen}"></i>\r
+            <i class="fa fa-th-list"></i>\r
+            <span>Gateway</span>\r
+        </div>\r
+        <div nodeType="exclusiveGateway" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M16.4,15l3.2-3.2c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0L15,13.6l-3.2-3.2c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4\r
+                        l3.2,3.2l-3.2,3.2c-0.4,0.4-0.4,1,0,1.4s1,0.4,1.4,0l3.2-3.2l3.2,3.2c0.4,0.4,1,0.4,1.4,0s0.4-1,0-1.4L16.4,15z"\r
+                    />\r
+                    <path class="st0" d="M29.1,12.9l-12-12c-1.1-1.1-3.1-1.1-4.2,0l-12,12C0.3,13.4,0,14.2,0,15s0.3,1.6,0.9,2.1l12,12\r
+                        c0.6,0.6,1.3,0.9,2.1,0.9s1.6-0.3,2.1-0.9l12-12c0.6-0.6,0.9-1.3,0.9-2.1S29.7,13.4,29.1,12.9z M27.7,15.7l-12,12\r
+                        c-0.4,0.4-1,0.4-1.4,0l-12-12C2.1,15.5,2,15.3,2,15s0.1-0.5,0.3-0.7l12-12C14.5,2.1,14.7,2,15,2s0.5,0.1,0.7,0.3l12,12\r
+                        c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />\r
+                </g>\r
+            </svg>\r
+            <span>EXCLUSIVE</span>\r
+        </div>\r
+        <div nodeType="parallelGateway" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M20.5,14H16V9.5c0-0.6-0.4-1-1-1s-1,0.4-1,1V14H9.5c-0.6,0-1,0.4-1,1s0.4,1,1,1H14v4.5c0,0.6,0.4,1,1,1\r
+                        s1-0.4,1-1V16h4.5c0.6,0,1-0.4,1-1S21.1,14,20.5,14z" />\r
+                    <path class="st0" d="M29.1,12.9l-12-12c-1.1-1.1-3.1-1.1-4.2,0l-12,12C0.3,13.4,0,14.2,0,15s0.3,1.6,0.9,2.1l12,12\r
+                        c0.6,0.6,1.3,0.9,2.1,0.9s1.6-0.3,2.1-0.9l12-12c0.6-0.6,0.9-1.3,0.9-2.1S29.7,13.4,29.1,12.9z M27.7,15.7l-12,12\r
+                        c-0.4,0.4-1,0.4-1.4,0l-12-12C2.1,15.5,2,15.3,2,15s0.1-0.5,0.3-0.7l12-12C14.5,2.1,14.7,2,15,2s0.5,0.1,0.7,0.3l12,12\r
+                        c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />\r
+                </g>\r
+            </svg>\r
+            <span>PARALLEL</span>\r
+        </div>\r
+    </accordion-group>\r
+    <!-- <accordion-group [isOpen]="true" #structural>\r
+        <div accordion-heading class="toolbar-head">\r
+            <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': structural?.isOpen, 'fa-chevron-right': !structural?.isOpen}"></i>\r
+            <i class="fa fa-th-list"></i>\r
+            <span>{{ 'WORKFLOW.BPMN_STRUCTURAL' | translate }}</span>\r
+        </div>\r
+        <div nodeType="subProcess" class="item ui-draggable">\r
+            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">\r
+                <g>\r
+                    <path class="st0" d="M24.5,1h-18c-2.8,0-5,2.2-5,5v18c0,2.8,2.2,5,5,5h18c2.8,0,5-2.2,5-5V6C29.5,3.2,27.2,1,24.5,1z M20.2,27h-9.4\r
+                        v-9.1c0-0.3,0.2-0.5,0.5-0.5h8.4c0.3,0,0.5,0.2,0.5,0.5V27z M27.5,24c0,1.7-1.3,3-3,3h-2.3v-9.1c0-1.4-1.1-2.5-2.5-2.5h-8.4\r
+                        c-1.4,0-2.5,1.1-2.5,2.5V27H6.5c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h18c1.7,0,3,1.3,3,3V24z"/>\r
+                    <path class="st0" d="M19,21.3h-2.5v-2.5c0-0.6-0.4-1-1-1c-0.6,0-1,0.4-1,1v2.5H12c-0.6,0-1,0.4-1,1s0.4,1,1,1h2.5v2.5\r
+                        c0,0.6,0.4,1,1,1c0.6,0,1-0.4,1-1v-2.5H19c0.6,0,1-0.4,1-1S19.5,21.3,19,21.3z"/>\r
+                </g>\r
+            </svg>\r
+            <span>{{ 'WORKFLOW.SUB_PROCESS' | translate }}</span>\r
+        </div>\r
+    </accordion-group> -->\r
+</accordion>\r
index 71bf02a..c204a19 100644 (file)
  *     ZTE - initial API and implementation and/or initial documentation\r
  */\r
 \r
-import { AfterViewInit, Component, OnInit } from '@angular/core';\r
+import { AfterViewChecked, Component, OnInit } from '@angular/core';\r
 \r
+import { BroadcastService } from '../../services/broadcast.service';\r
 import { JsPlumbService } from '../../services/jsplumb.service';\r
-import { NodeType } from "../../model/workflow/node-type.enum";\r
 \r
 /**\r
  * toolbar component contains some basic operations(save) and all of the supported workflow nodes.\r
@@ -24,29 +24,20 @@ import { NodeType } from "../../model/workflow/node-type.enum";
     templateUrl: 'toolbar.component.html',\r
     styleUrls: ['./toolbar.component.css']\r
 })\r
-export class ToolbarComponent implements AfterViewInit, OnInit {\r
-    public nodeTypes = [];\r
+export class ToolbarComponent implements AfterViewChecked, OnInit {\r
+    public isCatalog = true;\r
+    private needInitButton = true;\r
 \r
-    constructor(private jsPlumbService: JsPlumbService) {\r
-    }\r
-\r
-    public ngAfterViewInit() {\r
-        this.jsPlumbService.buttonDraggable();\r
-    }\r
+    constructor(private jsPlumbService: JsPlumbService, private broadcastService: BroadcastService) { }\r
 \r
-    ngOnInit(): void {\r
-        this.getNodeTypes();\r
+    public ngOnInit() {\r
     }\r
 \r
-    private getNodeTypes() {\r
-        for(let key in NodeType) {\r
-            if (typeof NodeType[key] === 'number') {\r
-                this.nodeTypes.push(key);\r
-            }\r
+    public ngAfterViewChecked() {\r
+        if (this.needInitButton) {\r
+            this.jsPlumbService.buttonDraggable();\r
+            this.jsPlumbService.buttonDroppable();\r
+            this.needInitButton = false;\r
         }\r
     }\r
-\r
-    public getNameByType(type:string):string{\r
-        return type.replace(type.charAt(0), type.charAt(0).toUpperCase());\r
-    }\r
 }\r
diff --git a/sdc-workflow-designer-ui/src/app/directive/drag-select/drag-select.directive.ts b/sdc-workflow-designer-ui/src/app/directive/drag-select/drag-select.directive.ts
deleted file mode 100644 (file)
index 395cf04..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/**\r
- * Copyright (c) 2017 ZTE Corporation.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * and the Apache License 2.0 which both accompany this distribution,\r
- * and are available at http://www.eclipse.org/legal/epl-v10.html\r
- * and http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Contributors:\r
- *     ZTE - initial API and implementation and/or initial documentation\r
- */\r
-\r
-import { AfterViewInit, Directive, ElementRef } from '@angular/core';\r
-import { JsPlumbService } from "../../services/jsplumb.service";\r
-\r
-@Directive({\r
-    selector: '[b4tDragSelect]'\r
-})\r
-export class DragSelectDirective implements AfterViewInit {\r
-    private selectBox: any;\r
-    public selecting = false;\r
-\r
-    public relatvieX: number;\r
-    public relatvieY: number;\r
-\r
-    public startX: number;\r
-    public startY: number;\r
-    public endX: number;\r
-    public endY: number;\r
-\r
-    public left: number = 0;\r
-    public top: number = 0;\r
-    public width: number = 0;\r
-    public height: number = 0;\r
-\r
-    constructor(private el: ElementRef, private jsPlumbService: JsPlumbService) { }\r
-\r
-    public ngAfterViewInit(): void {\r
-        this.selectBox = document.createElement('div');\r
-        const selectArea = this.el.nativeElement.appendChild(this.selectBox);\r
-        this.el.nativeElement.addEventListener("mousedown", (event: MouseEvent) => this.mouseDown(event));\r
-        this.el.nativeElement.addEventListener("mousemove", (event: MouseEvent) => this.mouseMove(event));\r
-        this.el.nativeElement.addEventListener("mouseup", (event: MouseEvent) => this.mouseUp(event));\r
-    }\r
-\r
-    public mouseDown(event: MouseEvent) {\r
-        this.relatvieX = event.clientX - event.offsetX;\r
-        this.relatvieY = event.clientY - event.offsetY;\r
-\r
-        this.width = 0;\r
-        this.height = 0;\r
-        this.startX = event.clientX;\r
-        this.startY = event.clientY;\r
-        this.endX = this.startX;\r
-        this.endY = this.startY;\r
-        this.selecting = true;\r
-        this.updateSelectArea();\r
-    }\r
-\r
-    public mouseMove(event: MouseEvent) {\r
-        this.endX = event.clientX;\r
-        this.endY = event.clientY;\r
-\r
-        this.updateSelectArea();\r
-    }\r
-\r
-    public mouseUp(event: MouseEvent) {\r
-        this.selecting = false;\r
-        this.updateSelectArea();\r
-    }\r
-\r
-    private updateSelectArea() {\r
-        if (this.selecting) {\r
-            this.selectBox.className = 'selecting';\r
-        } else {\r
-            this.selectBox.className = '';\r
-            return;\r
-        }\r
-\r
-        this.getAllSelectedNodes();\r
-\r
-        const leftTmp = this.startX >= this.endX ? this.endX : this.startX;\r
-        const topTmp = this.startY >= this.endY ? this.endY : this.startY;\r
-\r
-        this.left = leftTmp - this.relatvieX;\r
-        this.top = topTmp - this.relatvieY;\r
-\r
-        this.width = Math.abs(this.startX - this.endX);\r
-        this.height = Math.abs(this.endY - this.startY);\r
-\r
-        this.selectBox.style.top = this.top + 'px';\r
-        this.selectBox.style.left = this.left + 'px';\r
-        this.selectBox.style.width = this.width + 'px';\r
-        this.selectBox.style.height = this.height + 'px';\r
-    }\r
-\r
-    public getAllSelectedNodes() {\r
-        if(!this.selecting) {\r
-            return;\r
-        }\r
-        const selectedNodes = [];\r
-\r
-        const nodes = this.el.nativeElement.querySelectorAll('div.node');\r
-        nodes.forEach(node => {\r
-            if(this.checkNodeSelected(node)) {\r
-                selectedNodes.push(node);\r
-            }\r
-        });\r
-\r
-        this.jsPlumbService.jsplumbInstance.clearDragSelection();\r
-        this.jsPlumbService.jsplumbInstance.addToDragSelection(selectedNodes);\r
-\r
-    }\r
-\r
-    private checkNodeSelected(node: any): boolean {\r
-        const nodeLeft = node.offsetLeft;\r
-        const nodeTop = node.offsetTop;\r
-        const nodeRigth = nodeLeft + node.clientWidth;\r
-        const nodeBottom = nodeTop + node.clientHeight;\r
-\r
-        const selectedRight = this.left + this.width;\r
-        const selectedBottom = this.top + this.height;\r
-\r
-        return this.between(nodeLeft, this.left, selectedRight)\r
-            && this.between(nodeRigth, this.left, selectedRight)\r
-            && this.between(nodeTop, this.top, selectedBottom)\r
-            && this.between(nodeBottom, this.top, selectedBottom);\r
-    }\r
-\r
-    private between(value, min, max): boolean {\r
-        return min <= value && value <= max;\r
-    }\r
-\r
-}\r
diff --git a/sdc-workflow-designer-ui/src/app/directive/resizeable/resizable.directive.ts b/sdc-workflow-designer-ui/src/app/directive/resizeable/resizable.directive.ts
new file mode 100644 (file)
index 0000000..f591fe6
--- /dev/null
@@ -0,0 +1,42 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+import { AfterViewInit, Directive, ElementRef } from '@angular/core';\r
+import * as $ from 'jquery';\r
+\r
+import { JsPlumbService } from '../../services/jsplumb.service';\r
+import { ModelService } from '../../services/model.service';\r
+\r
+@Directive({ selector: '[b4tResizable]' })\r
+export class ResizableDirective implements AfterViewInit {\r
+\r
+    constructor(private el: ElementRef,\r
+                private jsPlumbService: JsPlumbService,\r
+                private planModelService: ModelService) {\r
+    }\r
+\r
+    public ngAfterViewInit() {\r
+        console.log('init resizble.');\r
+\r
+        $(this.el.nativeElement).resizable({\r
+            handles: 'all',\r
+            resize: (event, ui) => {\r
+                const element = ui.helper[0];\r
+                this.planModelService.updatePosition(element.id,\r
+                    element.offsetLeft, element.offsetTop, element.offsetWidth, element.offsetHeight - 12);\r
+                this.jsPlumbService.resizeParent(element, element.parentNode);\r
+                const node = this.planModelService.getNodeMap().get(element.id);\r
+                this.jsPlumbService.jsplumbInstanceMap.get(node.parentId).revalidate(element.id);\r
+            },\r
+        });\r
+    }\r
+}\r
diff --git a/sdc-workflow-designer-ui/src/app/model/rest-config.ts b/sdc-workflow-designer-ui/src/app/model/rest-config.ts
new file mode 100644 (file)
index 0000000..42dc46b
--- /dev/null
@@ -0,0 +1,17 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+import { Swagger } from './swagger';\r
+\r
+export class RestConfig {\r
+    constructor(public id: string, public name: string, public version: string, public url: string,\r
+        public swagger?: Swagger) { }\r
+}\r
@@ -1,16 +1,18 @@
-<!--
-/**
- * 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
- */
--->
-<div id="canvas" class="canvas" (click)="canvasClick()" b4tDragSelect>
-    <b4t-node *ngFor="let node of getWorkflow()?.nodes; let last = last;" [node]="node" [last]="last"></b4t-node>
-</div>
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+export class NodeTemplate {\r
+    public id: string;\r
+    public name: string;\r
+    public type: string;\r
+    public namespace: string;\r
+}\r
index fd08c8d..f76f659 100644 (file)
@@ -13,7 +13,7 @@
 export enum ValueSource {
     String,
     Plan,
+    Topology,
     Variable,
     Definition,
-    // Topology, // TODO implement Topology properties in R2
 }
index 300af89..e3fbcad 100644 (file)
@@ -1,4 +1,3 @@
-import {WorkflowNode} from './workflow-node';
 /**
  * Copyright (c) 2017 ZTE Corporation.
  * All rights reserved. This program and the accompanying materials
@@ -10,6 +9,7 @@ import {WorkflowNode} from './workflow-node';
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  */
+import {WorkflowNode} from './workflow-node';
 
-export class EndEvent extends WorkflowNode {
+export interface EndEvent extends WorkflowNode {
 }
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/error-event.ts b/sdc-workflow-designer-ui/src/app/model/workflow/error-event.ts
new file mode 100644 (file)
index 0000000..7285402
--- /dev/null
@@ -0,0 +1,18 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+import { ValueSource } from '../value-source.enum';\r
+import { Parameter } from './parameter';\r
+import { WorkflowNode } from './workflow-node';\r
+\r
+export interface ErrorEvent extends WorkflowNode {\r
+    parameter?: Parameter;\r
+}\r
index 13a3d1e..653e627 100644 (file)
@@ -12,7 +12,6 @@
 import { TimerEventDefinition, TimerEventDefinitionType } from './timer-event-definition';
 import { WorkflowNode } from './workflow-node';
 
-export class IntermediateCatchEvent extends WorkflowNode {
-    public timerEventDefinition: TimerEventDefinition =
-        new TimerEventDefinition(TimerEventDefinitionType[TimerEventDefinitionType.timeDuration]);
+export interface IntermediateCatchEvent extends WorkflowNode {
+    timerEventDefinition?: TimerEventDefinition;
 }
index 2481cdb..22170c1 100644 (file)
 export enum NodeType {
     startEvent,
     endEvent,
+    errorStartEvent,
+    errorEndEvent,
+    toscaNodeManagementTask,
     restTask,
-    intermediateCatchEvent,
     exclusiveGateway,
     parallelGateway,
-    scriptTask,
+    subProcess,
+    intermediateCatchEvent,
+    scriptTask
 }
index cc87a6f..67ca7f3 100644 (file)
@@ -15,6 +15,6 @@ import { ValueType } from '../value-type.enum';
 
 export class Parameter {
     constructor(public name: string, public value: string, public valueSource: string,
-                public type: string = ValueType[ValueType.String]) {
+                public type: string = ValueType[ValueType.String], public required: boolean = false) {
     }
 }
index ecea354..a7e4eee 100644 (file)
@@ -14,7 +14,7 @@ import { WorkflowNode } from './workflow-node';
 
 export class RestParameter extends Parameter {
     constructor(name: string, value: string, valueSource: string, type: string,
-                public position: string, public schema: any) {
-        super(name, value, valueSource, type);
+        public position: string, public schema: any, public required: boolean) {
+        super(name, value, valueSource, type, required);
     }
 }
index 2b3045d..12637d0 100644 (file)
@@ -9,17 +9,17 @@
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  */
+import { SwaggerResponse } from "../swagger";
 import { RestParameter } from './rest-parameter';
 import { WorkflowNode } from './workflow-node';
 
-export class RestTask extends WorkflowNode {
-    public serviceName: string;
-    public serviceVersion: string;
-    public url: string;
-    public method: string;
-    public operationId: string;
-    public produces: string[] = [];
-    public consumes: string[] = [];
-    public parameters: RestParameter[] = [];
-    public responses: any[] = [];
+export interface RestTask extends WorkflowNode {
+    restConfigId?: string;
+    path?: string;
+    method?: string;
+    operationId?: string;
+    produces?: string[];
+    consumes?: string[];
+    parameters?: RestParameter[];
+    responses?: SwaggerResponse[];
 }
index 3772226..392376a 100644 (file)
@@ -9,16 +9,9 @@
  * Contributors:\r
  *     ZTE - initial API and implementation and/or initial documentation\r
  */\r
-import { Position } from './position';\r
 import { WorkflowNode } from './workflow-node';\r
-import { SequenceFlow } from "./sequence-flow";\r
-\r
-export class ScriptTask extends WorkflowNode {\r
-    public scriptFormat: string;\r
-    public script: string;\r
-\r
-    public constructor(public id: string, public name: string, public type: string, public position: Position, public sequenceFlows: SequenceFlow[]) {\r
-        super(id, name, type, position, sequenceFlows);\r
-    }\r
 \r
+export interface ScriptTask extends WorkflowNode {\r
+    scriptFormat: string;\r
+    script?: string;\r
 }\r
index d609f7c..a8f6444 100644 (file)
@@ -12,6 +12,6 @@
 import { Parameter } from './parameter';
 import { WorkflowNode } from './workflow-node';
 
-export class StartEvent extends WorkflowNode {
-    public parameters: Parameter[] = [];
+export interface StartEvent extends WorkflowNode {
+    parameters?: Parameter[];
 }
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/sub-process.ts b/sdc-workflow-designer-ui/src/app/model/workflow/sub-process.ts
new file mode 100644 (file)
index 0000000..0da453e
--- /dev/null
@@ -0,0 +1,15 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+import { WorkflowNode } from './workflow-node';\r
+export interface SubProcess extends WorkflowNode {\r
+    children?: WorkflowNode[];\r
+}\r
index f78d397..101ef46 100644 (file)
@@ -17,11 +17,9 @@ export enum TimerEventDefinitionType {
     timeCycle,
 }
 
-export class TimerEventDefinition {
-    constructor(public type: string, // 'timeDate',  'timeCycle', 'timeDuration'
-        public timeDate?: string, // <timeDate>10/10/2099 00:00:00</timeDate>
-        public timeDuration?: string, // ISO 8601  P1Y3M5DT6H7M30S
-        public timeCycle?: string) { // ISO 8601  P1Y3M5DT6H7M30S
-
-    }
+export interface TimerEventDefinition extends WorkflowNode {
+    type: string; // 'timeDate',  'timeCycle', 'timeDuration'
+    timeDate?: string; // 2007-04-05T12:30-02:00
+    timeDuration?: string; // ISO 8601  P1Y3M5DT6H7M30S
+    timeCycle?: string; // ISO 8601  R5/P1Y2M10DT2H30M
 }
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/tosca-node-task.ts b/sdc-workflow-designer-ui/src/app/model/workflow/tosca-node-task.ts
new file mode 100644 (file)
index 0000000..986f018
--- /dev/null
@@ -0,0 +1,22 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+import { NodeTemplate } from '../topology/node-template';\r
+import { Parameter } from './parameter';\r
+import { WorkflowNode } from './workflow-node';\r
+\r
+export interface ToscaNodeTask extends WorkflowNode {\r
+    input?: Parameter[];\r
+    output?: Parameter[];\r
+    nodeInterface?: string;\r
+    operation?: string;\r
+    template?: NodeTemplate;\r
+}\r
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/workflow-element.ts b/sdc-workflow-designer-ui/src/app/model/workflow/workflow-element.ts
new file mode 100644 (file)
index 0000000..9b0e2fe
--- /dev/null
@@ -0,0 +1,14 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+export interface WorkflowElement {\r
+}\r
index 9e54be1..628148a 100644 (file)
@@ -9,9 +9,15 @@
  * Contributors:
  *     ZTE - initial API and implementation and/or initial documentation
  */
+import { WorkflowElement } from './workflow-element';
 import { Position } from './position';
 import { SequenceFlow } from './sequence-flow';
 
-export class WorkflowNode {
-    public constructor(public id: string, public name: string, public type: string, public position: Position, public sequenceFlows: SequenceFlow[]) {}
+export interface WorkflowNode extends WorkflowElement {
+    connection: SequenceFlow[];
+    id: string;
+    name: string;
+    parentId: string;
+    position: Position;
+    type: string;
 }
index dd75c45..544c2a7 100644 (file)
@@ -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();
 
index 084c055..5b2750b 100644 (file)
@@ -1,2 +1,2 @@
 \r
-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":""}]}};\r
+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":""}]}};\r
index f0013bc..c6cf60a 100644 (file)
 \r
 import { Injectable } from '@angular/core';\r
 import * as jsp from 'jsplumb';\r
-import { ModelService } from "./model.service";\r
-import { BroadcastService } from "./broadcast.service";\r
+\r
 import { Subscription } from 'rxjs/Subscription';\r
-import { WorkflowNode } from "../model/workflow/workflow-node";\r
+import { WorkflowNode } from '../model/workflow/workflow-node';\r
+import { BroadcastService } from './broadcast.service';\r
+import { ModelService } from './model.service';\r
+import { SequenceFlow } from '../model/workflow/sequence-flow';\r
+import { Position } from '../model/workflow/position';\r
 \r
 /**\r
  * JsPlumbService\r
@@ -23,68 +26,120 @@ import { WorkflowNode } from "../model/workflow/workflow-node";
  */\r
 @Injectable()\r
 export class JsPlumbService {\r
-    public jsplumbInstance;\r
+    public jsplumbInstanceMap = new Map<string, any>();\r
     public subscriptionMap = new Map<string, Subscription>();\r
 \r
-    constructor(private processService: ModelService, private broadcastService: BroadcastService) {\r
-        this.jsplumbInstance = jsp.jsPlumb.getInstance({\r
-            Container: 'canvas'\r
+    private padding = 20;\r
+    private rootClass = 'canvas';\r
+    private selectNodes: WorkflowNode[] = [];\r
+\r
+    constructor(private modelService: ModelService, private broadcastService: BroadcastService) {\r
+        this.broadcastService.selectedElement$.subscribe(elements => {\r
+            this.selectNodes = [];\r
+            if (elements && 0 < elements.length) {\r
+                for (let index = 0; index < elements.length; index++) {\r
+                    let element = elements[index];\r
+                    if (this.modelService.isNode(element)) {\r
+                        let node = element as WorkflowNode;\r
+                        this.selectNodes.push(node);\r
+                    }\r
+                }\r
+            }\r
         });\r
-        this.initJsPlumbInstance();\r
-        this.broadcastService.workflow.subscribe(Workflow => {\r
-            this.jsplumbInstance.reset();\r
-            this.unsubscriptionAll();\r
-            this.initJsPlumbInstance();\r
-            this.buttonDraggable();\r
-            this.buttonDroppable();\r
+    }\r
+\r
+    public connectChildrenNodes(parentNodeId: string) {\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(parentNodeId);\r
+\r
+        const nodes: WorkflowNode[] = this.modelService.getChildrenNodes(parentNodeId);\r
+        nodes.forEach(node => this.connect4OneNode(node, jsplumbInstance));\r
+    }\r
+\r
+    public connect4OneNode(node: WorkflowNode, jsplumbInstance: any) {\r
+        node.connection.forEach(sequenceFlow => {\r
+            const connection = jsplumbInstance.connect({\r
+                source: sequenceFlow.sourceRef,\r
+                target: sequenceFlow.targetRef,\r
+            });\r
+            if (sequenceFlow.name) {\r
+                connection.setLabel(sequenceFlow.name);\r
+            }\r
         });\r
     }\r
 \r
+    public initJsPlumbInstance(id: string) {\r
+        if (this.jsplumbInstanceMap.get(id)) {\r
+            return;\r
+        }\r
+        const jsplumbInstance = jsp.jsPlumb.getInstance();\r
 \r
-    public initJsPlumbInstance() {\r
-        this.jsplumbInstance.importDefaults({\r
-            Anchor: ['Top', 'RightMiddle', 'LeftMiddle', 'Bottom'],\r
-            Connector: [\r
-                'Flowchart',\r
-                { cornerRadius: 0, stub: 0, gap: 3 },\r
-            ],\r
-            ConnectionOverlays: [\r
-                [\r
-                    'Arrow',\r
-                    { direction: 1, foldback: 1, location: 1, width: 10, length: 10 },\r
-                ],\r
-                ['Label', { label: '', id: 'label', cssClass: 'aLabel' }],\r
-            ],\r
-            Endpoint: 'Blank',\r
+        jsplumbInstance.importDefaults({\r
+            Anchor: "Continuous",\r
+            Endpoint: "Blank",\r
+            Container: "pallete",\r
+            ReattachConnections: true,\r
+            Connector: ['Flowchart', {\r
+                stub: [0, 0],\r
+                cornerRadius: 5,\r
+                alwaysRespectStubs: true\r
+            }],\r
             PaintStyle: {\r
-                strokeWidth: 4,\r
-                stroke: 'black',\r
+                stroke: "#7D8695",\r
+                strokeWidth: 1,\r
+                radius: 1,\r
+                outlineStroke: "transform",\r
+                outlineWidth: 4\r
             },\r
-            HoverPaintStyle: {\r
-                strokeWidth: 4,\r
-                stroke: 'blue',\r
+            ConnectorStyle: {\r
+                stroke: "#7D8695",\r
+                strokeWidth: 1,\r
+                outlineStroke: "transform",\r
+                outlineWidth: 4\r
             },\r
+            ConnectorHoverStyle: {\r
+                stroke: "#00ABFF",\r
+                strokeWidth: 2,\r
+                outlineStroke: "transform",\r
+                outlineWidth: 4\r
+            },\r
+            ConnectionOverlays: [\r
+                ['Arrow', {\r
+                    location: 1,\r
+                    id: 'arrow',\r
+                    cssClass: 'icon-port',\r
+                    width: 11,\r
+                    length: 12\r
+                }],\r
+                ['Label', { label: '', id: 'label' }]\r
+            ]\r
         });\r
 \r
         // add connection to model data while a new connection is build\r
-        this.jsplumbInstance.bind('connection', info => {\r
-            this.processService.addSequenceFlow(info.connection.sourceId, info.connection.targetId);\r
+        jsplumbInstance.bind('connection', info => {\r
+            this.modelService.addConnection(info.connection.sourceId, info.connection.targetId);\r
 \r
             this.subscribe4Connection(info.connection);\r
 \r
-            info.connection.bind('click', connection => {\r
-                const sequenceFlow = this.processService.getSequenceFlow(connection.sourceId, connection.targetId);\r
-                this.broadcastService.broadcast(this.broadcastService.currentSequenceFlow, sequenceFlow);\r
-                this.broadcastService.broadcast(this.broadcastService.currentType, 'SequenceFlow');\r
+            info.connection.bind('click', (connection, event) => {\r
+                if ('Label' === connection.type) {\r
+                    return;\r
+                }\r
+                event.stopPropagation();\r
+                const sequenceFlow = this.modelService.getSequenceFlow(connection.sourceId, connection.targetId);\r
+                this.broadcastService.broadcast(this.broadcastService.showProperty, null);\r
+                this.broadcastService.broadcast(this.broadcastService.selectedElement, [sequenceFlow]);\r
             });\r
 \r
             info.connection.bind('dblclick', connection => {\r
-                const sequenceFlow = this.processService.getSequenceFlow(connection.sourceId, connection.targetId);\r
-                this.broadcastService.broadcast(this.broadcastService.sequenceFlow, sequenceFlow);\r
-                this.broadcastService.broadcast(this.broadcastService.showSequenceFlow, true);\r
+                if ('Label' === connection.type) {\r
+                    return;\r
+                }\r
+                const sequenceFlow = this.modelService.getSequenceFlow(connection.sourceId, connection.targetId);\r
+                this.broadcastService.broadcast(this.broadcastService.showProperty, sequenceFlow);\r
             });\r
         });\r
 \r
+        this.jsplumbInstanceMap.set(id, jsplumbInstance);\r
     }\r
 \r
     private subscribe4Connection(connection: any) {\r
@@ -94,128 +149,414 @@ export class JsPlumbService {
             sequenceFlowSubscription.unsubscribe();\r
         }\r
 \r
-        sequenceFlowSubscription = this.broadcastService.currentSequenceFlow$.subscribe(currentSequenceFlow => {\r
-            if (currentSequenceFlow.sourceRef === connection.sourceId\r
-                && currentSequenceFlow.targetRef === connection.targetId) {\r
-                connection.setPaintStyle({ stroke: 'red' });\r
+        let currentThis = this;\r
+        sequenceFlowSubscription = this.broadcastService.selectedElement$.subscribe(elements => {\r
+            let selected = false;\r
+            if (elements && 0 < elements.length) {\r
+                for (let index = 0; index < elements.length; index++) {\r
+                    let element = elements[index];\r
+                    if (!this.modelService.isNode(element)) {\r
+                        let sequence = element as SequenceFlow;\r
+                        if (sequence.sourceRef === connection.sourceId\r
+                            && sequence.targetRef === connection.targetId) {\r
+                            selected = true;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            if (selected) {\r
+                connection.setPaintStyle({\r
+                    stroke: '#00ABFF',\r
+                    strokeWidth: 1,\r
+                    radius: 1,\r
+                    outlineStroke: "transform",\r
+                    outlineWidth: 4\r
+                });\r
             } else {\r
-                connection.setPaintStyle({ stroke: 'black' });\r
+                connection.setPaintStyle({\r
+                    stroke: '#7D8695',\r
+                    strokeWidth: 1,\r
+                    radius: 1,\r
+                    outlineStroke: "transform",\r
+                    outlineWidth: 4\r
+                });\r
             }\r
         });\r
-\r
         this.subscriptionMap.set(pre + 'sequenceFlowSubscription', sequenceFlowSubscription);\r
-\r
-        let typeSubscription = this.subscriptionMap.get(pre + 'typeSubscription');\r
-        if (typeSubscription && !typeSubscription.closed) {\r
-            typeSubscription.unsubscribe();\r
-        }\r
-        typeSubscription = this.broadcastService.currentType$.subscribe(type => {\r
-            if (type === 'WorkflowNode') {\r
-                connection.setPaintStyle({ stroke: 'black' });\r
-            }\r
-        });\r
-        this.subscriptionMap.set(pre + 'typeSubscription', typeSubscription);\r
     }\r
 \r
     private unsubscription4Connection(connectionSelection: any) {\r
         connectionSelection.each(connection => {\r
             const pre = connection.sourceId + connection.targetId;\r
             this.subscriptionMap.get(pre + 'sequenceFlowSubscription').unsubscribe();\r
-            this.subscriptionMap.get(pre + 'typeSubscription').unsubscribe();\r
         });\r
     }\r
 \r
-    private unsubscriptionAll() {\r
-        this.subscriptionMap.forEach(subscription => subscription.unsubscribe());\r
+    public deleteConnect(sourceId: string, targetId: string) {\r
+        const sourceNode = this.modelService.getNodeMap().get(sourceId);\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(sourceNode.parentId);\r
+        const connectionSelection = jsplumbInstance.select({ source: sourceId, target: targetId });\r
+        this.unsubscription4Connection(connectionSelection);\r
+        connectionSelection.delete();\r
+    }\r
+\r
+    public setLabel(sourceId: string, targetId: string, label: string) {\r
+        const sourceNode = this.modelService.getNodeMap().get(sourceId);\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(sourceNode.parentId);\r
+        const connections = jsplumbInstance.select({ source: sourceId, target: targetId });\r
+        connections.setLabel(label);\r
     }\r
 \r
-    public initNode() {\r
-        this.processService.getProcess().forEach(node => {\r
-            this.jsplumbInstance.draggable(node.id, {\r
-                stop: event => {\r
-                    node.position.left = event.pos[0];\r
-                    node.position.top = event.pos[1];\r
-                },\r
-            });\r
+    public getParentNodeId(id: string): string {\r
+        const nodeElement = jsp.jsPlumb.getSelector('#' + id);\r
+        const parentNode = this.getParentNodeEl(nodeElement[0]);\r
 \r
-            this.jsplumbInstance.makeTarget(node.id, {\r
-                detachable: false,\r
-                isTarget: true,\r
-                maxConnections: -1,\r
-            });\r
+        return parentNode ? parentNode.id : null;\r
+    }\r
 \r
-            this.jsplumbInstance.makeSource(node.id, {\r
-                filter: '.anchor, .anchor *',\r
-                detachable: false,\r
-                isSource: true,\r
-                maxConnections: -1,\r
-            });\r
+    public initNode(node: WorkflowNode) {\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);\r
+\r
+        this.jsplumbInstanceMap.get(this.modelService.rootNodeId).draggable(node.id, {\r
+            scope: 'node',\r
+            filter: '.ui-resizable-handle',\r
+            classes: {\r
+                'ui-draggable': 'dragging'\r
+            },\r
+            // grid: [5, 5],\r
+            drag: event => {\r
+                // out of container edge, reset to minimal value.\r
+                if (0 > event.pos[0]) {\r
+                    event.el.style.left = '0px';\r
+                }\r
+                if (0 > event.pos[1]) {\r
+                    event.el.style.top = '0px';\r
+                }\r
+\r
+                if (0 < this.selectNodes.length) {\r
+                    let moveAll = false;\r
+                    this.selectNodes.forEach(element => {\r
+                        if (element.id === event.el.id) {\r
+                            moveAll = true;\r
+                        }\r
+                    });\r
+                    if (moveAll) {\r
+                        this.selectNodes.forEach(selectNode => {\r
+                            if (selectNode.id !== event.el.id) {\r
+                                selectNode.position.left += event.e.movementX;\r
+                                selectNode.position.left = 0 > selectNode.position.left ? 0 : selectNode.position.left;\r
+                                selectNode.position.top += event.e.movementY;\r
+                                selectNode.position.top = 0 > selectNode.position.top ? 0 : selectNode.position.top;\r
+                            }\r
+                            jsplumbInstance.revalidate(jsplumbInstance.getSelector('#' + selectNode.id));\r
+                        });\r
+                    }\r
+                }\r
+            },\r
+            stop: event => {\r
+                this.selectNodes.forEach(selectNode => {\r
+                    jsplumbInstance.revalidate(jsplumbInstance.getSelector('#' + selectNode.id));\r
+                });\r
+            }\r
+        });\r
+\r
+        jsplumbInstance.makeTarget(node.id, {\r
+            maxConnections: -1,\r
+            beforeDrop: function (info) {\r
+                const sourceId = info.sourceId;\r
+                const targetId = info.targetId;\r
+                if (sourceId === targetId) {\r
+                    return false;\r
+                }\r
+                const sameConnections = this.instance.getConnections({ source: sourceId, target: targetId });\r
+                if (sameConnections && 0 < sameConnections.length) {\r
+                    return false;\r
+                }\r
+                return true;\r
+            }\r
+\r
+        });\r
+\r
+        jsplumbInstance.makeSource(node.id, {\r
+            filter: '.anchor, .anchor *',\r
+            maxConnections: -1,\r
         });\r
     }\r
 \r
-    public connectNodes() {\r
-        const nodes: WorkflowNode[] = this.processService.getProcess();\r
-        nodes.forEach(node => this.connect4OneNode(node));\r
+    public nodeDroppable(node: WorkflowNode, rank: number) {\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);\r
+\r
+        const selector = jsplumbInstance.getSelector('#' + node.id);\r
+        this.jsplumbInstanceMap.get(this.modelService.rootNodeId).droppable(selector, {\r
+            scope: 'node',\r
+            rank,\r
+            tolerance: 'pointer',\r
+            drop: event => {\r
+                if (!this.isChildNode(event.drop.el, event.drag.el)) {\r
+                    this.drop(event);\r
+                }\r
+                return true;\r
+            },\r
+            canDrop: drag => {\r
+                const nodeMap = this.modelService.getNodeMap();\r
+                const ancestorNode = nodeMap.get(drag.el.id);\r
+\r
+                const isAncestor = this.modelService.isDescendantNode(ancestorNode, node.id);\r
+                return !isAncestor;\r
+            },\r
+        });\r
     }\r
 \r
-    public connect4OneNode(node: WorkflowNode) {\r
-        node.sequenceFlows.forEach(sequenceFlow => {\r
-            const connection = this.jsplumbInstance.connect({\r
-                source: sequenceFlow.sourceRef,\r
-                target: sequenceFlow.targetRef,\r
-            });\r
-            if (sequenceFlow.name) {\r
-                connection.setLabel(sequenceFlow.name);\r
+    private isChildNode(childElement, parentElement) {\r
+        while (childElement !== parentElement) {\r
+            childElement = childElement.parentNode;\r
+            if (childElement.classList.contains('canvas')) {\r
+                return false;\r
             }\r
-        });\r
+        }\r
+\r
+        return true;\r
     }\r
 \r
-    public setLabel(sourceId: string, targetId: string, label: string) {\r
-        const sourceNode = this.processService.getNodeById(sourceId);\r
-        const connections = this.jsplumbInstance.select({ source: sourceId, target: targetId });\r
-        connections.setLabel(label);\r
+    private drop(event) {\r
+        const dragEl = event.drag.el;\r
+        const dropEl = event.drop.el;\r
+\r
+        this.resizeParent(dragEl, dropEl);\r
+\r
+        const nodeLeft = dragEl.getBoundingClientRect().left;\r
+        const nodeTop = dragEl.getBoundingClientRect().top;\r
+        const parentLeft = dropEl.getBoundingClientRect().left;\r
+        const parentTop = dropEl.getBoundingClientRect().top;\r
+        const left = nodeLeft - parentLeft + dropEl.scrollLeft;\r
+        const top = nodeTop - parentTop + dropEl.scrollTop;\r
+        dragEl.style.top = top + 'px';\r
+        dragEl.style.left = left + 'px';\r
+\r
+        // 12 is title height\r
+        this.modelService.updatePosition(dragEl.id, left, top, dragEl.getBoundingClientRect().width, dragEl.getBoundingClientRect().height - 12);\r
+\r
+        const originalParentNode = this.getParentNodeEl(dragEl);\r
+        const originalParentNodeId = originalParentNode ? originalParentNode.id : this.modelService.rootNodeId;\r
+\r
+        const targetParentNodeId = dropEl.classList.contains('node') ? dropEl.id : this.modelService.rootNodeId;\r
+        this.changeParent(dragEl.id, originalParentNodeId, targetParentNodeId);\r
     }\r
 \r
-    public deleteConnect(sourceId: string, targetId: string) {\r
-        const sourceNode = this.processService.getNodeById(sourceId);\r
-        const connectionSelection = this.jsplumbInstance.select({ source: sourceId, target: targetId });\r
-        this.unsubscription4Connection(connectionSelection);\r
-        connectionSelection.delete();\r
+    private changeParent(id: string, originalParentNodeId: string, targetParentNodeId: string) {\r
+        if (originalParentNodeId !== targetParentNodeId) {\r
+            this.jsplumbInstanceMap.get(originalParentNodeId).removeAllEndpoints(id);\r
+            this.modelService.changeParent(id, originalParentNodeId, targetParentNodeId);\r
+        }\r
     }\r
 \r
-    public remove(nodeId: string) {\r
-        // unsubscription4Connection\r
-        const connectionsAsSource = this.jsplumbInstance.select({ source: nodeId });\r
-        this.unsubscription4Connection(connectionsAsSource);\r
-        const connectionsAsTarget = this.jsplumbInstance.select({ target: nodeId });\r
-        this.unsubscription4Connection(connectionsAsTarget);\r
+    private getParentNodeEl(element) {\r
+        while (!(element.parentNode.classList.contains('node') || element.parentNode.classList.contains('canvas'))) {\r
+            element = element.parentNode;\r
+        }\r
 \r
-        this.jsplumbInstance.remove(nodeId);\r
+        if (element.parentNode.classList.contains('canvas')) { // top level node\r
+            return null;\r
+        } else {\r
+            return element.parentNode;\r
+        }\r
+    }\r
+\r
+    public canvasDroppable() {\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);\r
+        const canvasSelector = jsplumbInstance.getSelector('.canvas');\r
+        jsplumbInstance.droppable(canvasSelector, {\r
+            scope: 'node',\r
+            rank: 0,\r
+            grid: [5, 5],\r
+            drop: event => this.drop(event),\r
+        });\r
     }\r
 \r
     public buttonDraggable() {\r
-        const selector = this.jsplumbInstance.getSelector('.toolbar .item');\r
-        this.jsplumbInstance.draggable(selector,\r
-            {\r
-                scope: 'btn',\r
-                clone: true,\r
-            });\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);\r
+        const selector = jsplumbInstance.getSelector('.item');\r
+        jsplumbInstance.draggable(selector, {\r
+            scope: 'btn',\r
+            clone: true\r
+        });\r
     }\r
 \r
     public buttonDroppable() {\r
-        const selector = this.jsplumbInstance.getSelector('.canvas');\r
-        this.jsplumbInstance.droppable(selector, {\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);\r
+        const selector = jsplumbInstance.getSelector('.canvas');\r
+        jsplumbInstance.droppable(selector, {\r
             scope: 'btn',\r
+            // grid: [5, 5],\r
             drop: event => {\r
-                const el = this.jsplumbInstance.getSelector(event.drag.el);\r
+                const el = jsplumbInstance.getSelector(event.drag.el);\r
                 const type = el.attributes.nodeType.value;\r
-                // Mouse position minus drop canvas start position and minus icon half size\r
-                const left = event.e.clientX - 220 - (event.e.offsetX / 2);\r
-                const top = event.e.clientY - 70 - (event.e.offsetY / 2);\r
-\r
-                this.processService.addNode(type, type, top, left);\r
+                // Mouse position minus drop canvas start position plus scroll position.\r
+                let left = event.e.x - event.drop.pagePosition[0] + event.drop.el.scrollLeft;\r
+                let top = event.e.y - event.drop.pagePosition[1] + event.drop.el.scrollTop;\r
+                if (0 > left) {\r
+                    left = 0;\r
+                }\r
+                if (0 > top) {\r
+                    top = 0;\r
+                }\r
+                const name = event.drag.el.children[1].innerText;\r
+                this.modelService.addNode(name, type, left, top);\r
             },\r
         });\r
     }\r
 \r
+    public remove(node: WorkflowNode) {\r
+        const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);\r
+\r
+        // unsubscription4Connection\r
+        const connectionsAsSource = jsplumbInstance.select({ source: node.id });\r
+        this.unsubscription4Connection(connectionsAsSource);\r
+        const connectionsAsTarget = jsplumbInstance.select({ target: node.id });\r
+        this.unsubscription4Connection(connectionsAsTarget);\r
+\r
+        jsplumbInstance.remove(node.id);\r
+    }\r
+\r
+    public resizeParent(element: any, parentElement: any) {\r
+        if (parentElement.classList.contains(this.rootClass)) {\r
+            return;\r
+        }\r
+\r
+        if (!parentElement.classList.contains('node')) {\r
+            this.resizeParent(element, parentElement.parentNode);\r
+            return;\r
+        }\r
+\r
+        const leftResized = this.resizeParentLeft(element, parentElement);\r
+        const rightResized = this.resizeParentRight(element, parentElement);\r
+        const topResized = this.resizeParentTop(element, parentElement);\r
+        const bottomResized = this.resizeParentBottom(element, parentElement);\r
+\r
+        if (leftResized || rightResized || topResized || bottomResized) {\r
+            if (parentElement.classList.contains('node')) {\r
+                const rect = parentElement.getBoundingClientRect();\r
+                this.modelService.updatePosition(parentElement.id,\r
+                    parentElement.offsetLeft,\r
+                    parentElement.offsetTop,\r
+                    // title height\r
+                    rect.width, rect.height - 12);\r
+            }\r
+            this.resizeParent(parentElement, parentElement.parentNode);\r
+        }\r
+    }\r
+\r
+    private resizeParentLeft(element: any, parentElement: any): boolean {\r
+        let resized = false;\r
+\r
+        const actualLeft = element.getBoundingClientRect().left;\r
+        const actualParentLeft = parentElement.getBoundingClientRect().left;\r
+\r
+        if (actualLeft - this.padding < actualParentLeft) {\r
+            const width = actualParentLeft - actualLeft + this.padding;\r
+\r
+            this.translateElement(parentElement, -width, 0, width, 0);\r
+            this.translateChildren(parentElement, element, width, 0);\r
+            resized = true;\r
+        }\r
+\r
+        return resized;\r
+    }\r
+\r
+    private resizeParentRight(element: any, parentElement: any): boolean {\r
+        let resized = false;\r
+\r
+        const actualLeft = element.getBoundingClientRect().left;\r
+        const actualRight = actualLeft + element.offsetWidth;\r
+\r
+        const actualParentLeft = parentElement.getBoundingClientRect().left;\r
+\r
+        if ((actualParentLeft + parentElement.offsetWidth) < actualRight + this.padding) {\r
+            this.setElementWidth(parentElement, actualRight + this.padding - actualParentLeft);\r
+            resized = true;\r
+        }\r
+\r
+        return resized;\r
+    }\r
+\r
+    private resizeParentBottom(element: any, parentElement: any): boolean {\r
+        let resized = false;\r
+\r
+        const actualTop = element.getBoundingClientRect().top;\r
+        const actualBottom = actualTop + element.offsetHeight;\r
+\r
+        const actualParentTop = parentElement.getBoundingClientRect().top;\r
+        const actualParentBottom = actualParentTop + parentElement.offsetHeight;\r
+\r
+        if (actualParentBottom < actualBottom + this.padding) {\r
+            this.setElementHeight(parentElement, actualBottom + this.padding - actualParentTop);\r
+            resized = true;\r
+        }\r
+\r
+        return resized;\r
+    }\r
+\r
+    private resizeParentTop(element: any, parentElement: any): boolean {\r
+        let resized = false;\r
+\r
+        const actualTop = element.getBoundingClientRect().top;\r
+        const actualParentTop = parentElement.getBoundingClientRect().top;\r
+\r
+        if (actualTop - this.padding < actualParentTop) {\r
+            const height = actualParentTop - actualTop + this.padding;\r
+\r
+            this.translateElement(parentElement, 0, -height, 0, height);\r
+            this.translateChildren(parentElement, element, 0, height);\r
+            resized = true;\r
+        }\r
+\r
+        return resized;\r
+    }\r
+\r
+    private translateElement(element, left: number, top: number, width: number, height: number) {\r
+        const offsetLeft = element.offsetLeft + left;\r
+        element.style.left = offsetLeft + 'px';\r
+\r
+        const offsetTop = element.offsetTop + top;\r
+        element.style.top = offsetTop + 'px';\r
+\r
+        const offsetWidth = element.offsetWidth + width;\r
+        element.style.width = offsetWidth + 'px';\r
+\r
+        const offsetHeight = element.offsetHeight + height;\r
+        element.style.height = offsetHeight + 'px';\r
+\r
+        if (element.classList.contains('node')) {\r
+            const node = this.modelService.getNodeMap().get(element.id);\r
+            this.jsplumbInstanceMap.get(node.parentId).revalidate(element.id);\r
+        }\r
+    }\r
+\r
+    private translateChildren(parentElment, excludeElement, left: number, top: number) {\r
+        const len = parentElment.children.length;\r
+        for (let i = 0; i < len; i++) {\r
+            const childElment = parentElment.children[i];\r
+            if (childElment.localName === 'b4t-node') {\r
+                this.translateElement(childElment.children[0], left, top, 0, 0);\r
+            }\r
+        }\r
+    }\r
+\r
+    private setElementHeight(element, height: number) {\r
+        element.style.height = height + 'px';\r
+    }\r
+\r
+    private setElementWidth(element, width: number) {\r
+        element.style.width = width + 'px';\r
+    }\r
+\r
+    private getActualPosition(element, offset: string) {\r
+        let actualPosition = element[offset];\r
+        let current = element.offsetParent;\r
+        while (current !== null) {\r
+            actualPosition += element[offset];\r
+            current = current.offsetParent;\r
+        }\r
+        return actualPosition;\r
+    }\r
 }\r
index 6ce49d0..65d3e49 100644 (file)
@@ -18,12 +18,22 @@ import { NodeType } from "../model/workflow/node-type.enum";
 import { StartEvent } from "../model/workflow/start-event";\r
 import { SequenceFlow } from "../model/workflow/sequence-flow";\r
 import { RestTask } from "../model/workflow/rest-task";\r
+import { ErrorEvent } from "../model/workflow/error-event";\r
 import { PlanTreeviewItem } from "../model/plan-treeview-item";\r
 import { WorkflowConfigService } from "./workflow-config.service";\r
 import { Swagger, SwaggerModelSimple, SwaggerReferenceObject } from "../model/swagger";\r
 import { WorkflowService } from "./workflow.service";\r
 import { IntermediateCatchEvent } from "../model/workflow/intermediate-catch-event";\r
 import { ScriptTask } from "../model/workflow/script-task";\r
+import { ToscaNodeTask } from '../model/workflow/tosca-node-task';\r
+import { NodeTemplate } from '../model/topology/node-template';\r
+import { SubProcess } from '../model/workflow/sub-process';\r
+import { TimerEventDefinition, TimerEventDefinitionType } from '../model/workflow/timer-event-definition';\r
+import { Parameter } from '../model/workflow/parameter';\r
+import { ValueSource } from '../model/value-source.enum';\r
+import { RestService } from './rest.service';\r
+import { BroadcastService } from './broadcast.service';\r
+import { RestConfig } from '../model/rest-config';\r
 \r
 /**\r
  * WorkflowService\r
@@ -31,78 +41,231 @@ import { ScriptTask } from "../model/workflow/script-task";
  */\r
 @Injectable()\r
 export class ModelService {\r
-\r
-    constructor(private workflowService: WorkflowService, private configService: WorkflowConfigService) {\r
-\r
+    public rootNodeId = 'root';\r
+\r
+    private planModel: PlanModel = new PlanModel();\r
+\r
+    constructor(private broadcastService: BroadcastService, private restService: RestService, private workflowService: WorkflowService, private configService: WorkflowConfigService) {\r
+        this.broadcastService.planModel$.subscribe(plan => {\r
+            plan.nodes.forEach(node => {\r
+                switch (node.type) {\r
+                    case NodeType[NodeType.startEvent]:\r
+                        node.position.width = 56;\r
+                        node.position.height = 56;\r
+                        break;\r
+                    case NodeType[NodeType.endEvent]:\r
+                        node.position.width = 56;\r
+                        node.position.height = 56;\r
+                        break;\r
+                    case NodeType[NodeType.restTask]:\r
+                        node.position.width = 56;\r
+                        node.position.height = 56;\r
+                        break;\r
+                    case NodeType[NodeType.errorStartEvent]:\r
+                    case NodeType[NodeType.errorEndEvent]:\r
+                        node.position.width = 26;\r
+                        node.position.height = 26;\r
+                        break;\r
+                    case NodeType[NodeType.toscaNodeManagementTask]:\r
+                        node.position.width = 56;\r
+                        node.position.height = 56;\r
+                        break;\r
+                    case NodeType[NodeType.subProcess]:\r
+                        node.position.width = 56;\r
+                        node.position.height = 56;\r
+                        break;\r
+                    case NodeType[NodeType.intermediateCatchEvent]:\r
+                        node.position.width = 56;\r
+                        node.position.height = 56;\r
+                        break;\r
+                    case NodeType[NodeType.scriptTask]:\r
+                        node.position.width = 56;\r
+                        node.position.height = 56;\r
+                        break;\r
+                    case NodeType[NodeType.exclusiveGateway]:\r
+                    case NodeType[NodeType.parallelGateway]:\r
+                        node.position.width = 26;\r
+                        node.position.height = 26;\r
+                        break;\r
+                    default:\r
+                        node.position.width = 56;\r
+                        node.position.height = 56;\r
+                        break;\r
+                }\r
+            });\r
+            this.planModel = plan;\r
+        });\r
+        this.broadcastService.updateModelRestConfig$.subscribe(restConfigs => {\r
+            this.updateRestConfig(restConfigs);\r
+        });\r
     }\r
 \r
     public getProcess(): WorkflowNode[] {\r
         return this.workflowService.planModel.nodes;\r
     }\r
 \r
-    public addNode(name: string, type: string, top: number, left: number): WorkflowNode {\r
-        let node: WorkflowNode;\r
-        switch (type) {\r
-            case NodeType[NodeType.startEvent]:\r
-                node = new StartEvent(this.createId(), name, type, new Position(top, left), []);\r
-                break;\r
-            case NodeType[NodeType.restTask]:\r
-                node = new RestTask(this.createId(), name, type, new Position(top, left), []);\r
-                break;\r
-            case NodeType[NodeType.intermediateCatchEvent]:\r
-                node = new IntermediateCatchEvent(this.createId(), name, type, new Position(top, left), []);\r
-                break;\r
-            case NodeType[NodeType.scriptTask]:\r
-                node = new ScriptTask(this.createId(), name, type, new Position(top, left), []);\r
-                break;\r
-            default:\r
-                node = new WorkflowNode(this.createId(), name, type, new Position(top, left), []);\r
-                break;\r
+    public getNodes(): WorkflowNode[] {\r
+        return this.planModel.nodes;\r
+    }\r
+\r
+    public addConnection(sourceId: string, targetId: string) {\r
+        const node = this.getNodeMap().get(sourceId);\r
+        if (node) {\r
+            const index = node.connection.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);\r
+            if (index === -1) {\r
+                const sequenceFlow: SequenceFlow = { sourceRef: sourceId, targetRef: targetId };\r
+                node.connection.push(sequenceFlow);\r
+            }\r
         }\r
+    }\r
 \r
-        this.getProcess().push(node);\r
-        return node;\r
+    public deleteConnection(sourceId: string, targetId: string) {\r
+        const node = this.getNodeMap().get(sourceId);\r
+        if (node) {\r
+            const index = node.connection.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);\r
+            if (index !== -1) {\r
+                node.connection.splice(index, 1);\r
+            }\r
+        }\r
     }\r
 \r
-    public deleteNode(nodeId: string): WorkflowNode {\r
+    public deleteNode(parentId: string, nodeId: string): WorkflowNode {\r
+        const nodeMap = this.getNodeMap();\r
+\r
+        const nodes = this.getChildrenNodes(parentId);\r
+\r
         // delete related connections\r
-        this.getProcess().forEach(node => this.deleteSequenceFlow(node.id, nodeId));\r
+        nodes.forEach(node => this.deleteConnection(node.id, nodeId));\r
 \r
         // delete current node\r
-        const index = this.getProcess().findIndex(node => node.id === nodeId);\r
+        const index = nodes.findIndex(node => node.id === nodeId);\r
         if (index !== -1) {\r
-            const node = this.getProcess().splice(index, 1)[0];\r
-            node.sequenceFlows = [];\r
+            const node = nodes.splice(index, 1)[0];\r
+            node.connection = [];\r
             return node;\r
         }\r
 \r
-        return undefined;\r
+        return null;\r
     }\r
 \r
-    public addSequenceFlow(sourceId: string, targetId: string) {\r
-        const node = this.getNodeById(sourceId);\r
-        if (node) {\r
-            const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);\r
-            if (index === -1) {\r
-                node.sequenceFlows.push(new SequenceFlow(sourceId, targetId));\r
-            }\r
+    public addChild(parentId: string, child: WorkflowNode) {\r
+        this.getChildrenNodes(parentId).push(child);\r
+    }\r
+\r
+    public deleteChild(node: SubProcess, id: string): WorkflowNode {\r
+        const index = node.children.findIndex(child => child.id === id);\r
+        if (index !== -1) {\r
+            const deletedNode = node.children.splice(index, 1);\r
+            return deletedNode[0];\r
         }\r
+\r
+        return null;\r
     }\r
 \r
-    public deleteSequenceFlow(sourceId: string, targetId: string) {\r
-        const node = this.getNodeById(sourceId);\r
-        if (node) {\r
-            const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);\r
-            if (index !== -1) {\r
-                node.sequenceFlows.splice(index, 1);\r
+    public updateRestConfig(restConfigs: RestConfig[]): void {\r
+        this.planModel.configs = { restConfigs: restConfigs };\r
+        // console.log(this.planModel.configs);\r
+    }\r
+\r
+    public getNodeMap(): Map<string, WorkflowNode> {\r
+        const map = new Map<string, WorkflowNode>();\r
+        this.toNodeMap(this.planModel.nodes, map);\r
+        return map;\r
+    }\r
+\r
+    private toNodeMap(nodes: WorkflowNode[], map: Map<string, WorkflowNode>) {\r
+        nodes.forEach(node => {\r
+            if (node.type === 'subProcess') {\r
+                this.toNodeMap((<SubProcess>node).children, map);\r
             }\r
+            map.set(node.id, node);\r
+        });\r
+    }\r
+\r
+    public addNode(name: string, type: string, left: number, top: number) {\r
+        const id = this.createId();\r
+        const workflowPos = new Position(left, top);\r
+        const node = this.createNodeByType(id, name, type, workflowPos);\r
+        this.planModel.nodes.push(node);\r
+    }\r
+\r
+    private createNodeByType(id: string, name: string, type: string, position: Position): WorkflowNode {\r
+        const bigPosition = new Position(position.left, position.top, 56, 56);\r
+        const smallPosition = new Position(position.left, position.top, 26, 26);\r
+        switch (type) {\r
+            case NodeType[NodeType.startEvent]:\r
+                let startEventNode: StartEvent = {\r
+                    id: id, type: type, name: name, parentId: this.rootNodeId,\r
+                    position: bigPosition, connection: [], parameters: []\r
+                };\r
+                return startEventNode;\r
+            case NodeType[NodeType.endEvent]:\r
+                let endEventNode: WorkflowNode = {\r
+                    id: id, type: type, name: name, parentId: this.rootNodeId,\r
+                    position: bigPosition, connection: []\r
+                };\r
+                return endEventNode;\r
+            case NodeType[NodeType.restTask]:\r
+                let restTaskNode: RestTask = {\r
+                    id: id, type: type, name: name, parentId: this.rootNodeId,\r
+                    position: bigPosition, connection: [], produces: [], consumes: [], parameters: [], responses: []\r
+                };\r
+                return restTaskNode;\r
+            case NodeType[NodeType.errorStartEvent]:\r
+            case NodeType[NodeType.errorEndEvent]:\r
+                let errorEventNode: ErrorEvent = {\r
+                    id: id, type: type, name: '', parentId: this.rootNodeId,\r
+                    position: smallPosition, connection: [], parameter: new Parameter('errorRef', '', ValueSource[ValueSource.String])\r
+                };\r
+                return errorEventNode;\r
+            case NodeType[NodeType.toscaNodeManagementTask]:\r
+                let toscaNodeTask: ToscaNodeTask = {\r
+                    id: id, type: type, name: name, parentId: this.rootNodeId,\r
+                    position: bigPosition, connection: [], input: [], output: [], template: new NodeTemplate()\r
+                };\r
+                return toscaNodeTask;\r
+            case NodeType[NodeType.subProcess]:\r
+                let subProcess: SubProcess = {\r
+                    id: id, type: type, name: name, parentId: this.rootNodeId,\r
+                    position: bigPosition, connection: [], children: []\r
+                };\r
+                return subProcess;\r
+            case NodeType[NodeType.intermediateCatchEvent]:\r
+                let intermediateCatchEvent: IntermediateCatchEvent = {\r
+                    id: id, type: type, name: name, parentId: this.rootNodeId,\r
+                    position: bigPosition, connection: [], timerEventDefinition: <TimerEventDefinition>{ type: TimerEventDefinitionType[TimerEventDefinitionType.timeDuration] }\r
+                };\r
+                return intermediateCatchEvent;\r
+            case NodeType[NodeType.scriptTask]:\r
+                let scriptTask: ScriptTask = {\r
+                    id: id, type: type, name: name, parentId: this.rootNodeId,\r
+                    position: bigPosition, connection: [], scriptFormat: 'JavaScript'\r
+                };\r
+                return scriptTask;\r
+            case NodeType[NodeType.exclusiveGateway]:\r
+            case NodeType[NodeType.parallelGateway]:\r
+                let getway: WorkflowNode = {\r
+                    id: id, type: type, name: '', parentId: this.rootNodeId,\r
+                    position: smallPosition, connection: []\r
+                };\r
+                return getway;\r
+            default:\r
+                let node: WorkflowNode = {\r
+                    id: id, type: type, name: name, parentId: this.rootNodeId,\r
+                    position: bigPosition, connection: []\r
+                };\r
+                return node;\r
         }\r
     }\r
 \r
+    public isNode(object: any): boolean {\r
+        return undefined !== object.type;\r
+    }\r
+\r
     public getSequenceFlow(sourceRef: string, targetRef: string): SequenceFlow {\r
         const node = this.getNodeById(sourceRef);\r
         if (node) {\r
-            const sequenceFlow = node.sequenceFlows.find(tmp => tmp.targetRef === targetRef);\r
+            const sequenceFlow = node.connection.find(tmp => tmp.targetRef === targetRef);\r
             return sequenceFlow;\r
         } else {\r
             return undefined;\r
@@ -123,6 +286,9 @@ export class ModelService {
                 case NodeType[NodeType.startEvent]:\r
                     params.push(this.loadOutput4StartEvent(<StartEvent>node));\r
                     break;\r
+                case NodeType[NodeType.toscaNodeManagementTask]:\r
+                    params.push(this.loadOutput4ToscaNodeTask(<ToscaNodeTask>node));\r
+                    break;\r
                 case NodeType[NodeType.restTask]:\r
                     params.push(this.loadOutput4RestTask(<RestTask>node));\r
                     break;\r
@@ -135,54 +301,73 @@ export class ModelService {
     }\r
 \r
     private loadOutput4StartEvent(node: StartEvent): PlanTreeviewItem {\r
-        const startItem = new PlanTreeviewItem(node.name, `[${node.id}]`, []);\r
+        const startItem = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);\r
         node.parameters.map(param =>\r
             startItem.children.push(new PlanTreeviewItem(param.name, `[${param.name}]`, [])));\r
         return startItem;\r
     }\r
 \r
+    private loadOutput4ToscaNodeTask(node: ToscaNodeTask): PlanTreeviewItem {\r
+        const item = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);\r
+        item.children.push(this.createStatusCodeTreeViewItem(node.id));\r
+        const responseItem = this.createResponseTreeViewItem(node.id);\r
+        item.children.push(responseItem);\r
+\r
+        node.output.map(param =>\r
+            responseItem.children.push(new PlanTreeviewItem(param.name, `${responseItem.value}.[${param.name}]`, [])));\r
+        return item;\r
+    }\r
+\r
     private loadOutput4RestTask(node: RestTask): PlanTreeviewItem {\r
-        const item = new PlanTreeviewItem(node.name, `[${node.id}]`, []);\r
+        const item = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);\r
         item.children.push(this.createStatusCodeTreeViewItem(node.id));\r
 \r
         if (node.responses.length !== 0) { // load rest responses\r
             const responseItem = this.createResponseTreeViewItem(node.id);\r
             item.children.push(responseItem);\r
+            // todo: should list all available response or only the first one?\r
             if (node.responses[0]) {\r
-                const swagger = this.configService.getSwaggerInfo(node.serviceName, node.serviceVersion);\r
-                const swaggerDefinition = this.configService.getDefinition(swagger, node.responses[0].schema.$ref);\r
-                this.loadParamsBySwaggerDefinition(responseItem, swagger, <SwaggerModelSimple>swaggerDefinition);\r
+                const swagger = this.restService.getSwaggerInfo(node.restConfigId);\r
+                const SwaggerReferenceObject = node.responses[0].schema as SwaggerReferenceObject;\r
+                const swaggerDefinition = this.restService.getDefinition(swagger, SwaggerReferenceObject.$ref);\r
+                this.loadParamsBySwaggerDefinition(responseItem, swagger, swaggerDefinition);\r
             }\r
         }\r
 \r
         return item;\r
     }\r
 \r
-    private createStatusCodeTreeViewItem(nodeId: string): PlanTreeviewItem {\r
-        return new PlanTreeviewItem('statusCode', `[${nodeId}].[statusCode]`, []);\r
-    }\r
-\r
-    private createResponseTreeViewItem(nodeId: string): PlanTreeviewItem {\r
-        return new PlanTreeviewItem('response', `[${nodeId}].[responseBody]`, []);\r
-    }\r
-\r
-    private loadParamsBySwaggerDefinition(parentItem: PlanTreeviewItem, swagger: Swagger, definition: SwaggerModelSimple) {\r
+    private loadParamsBySwaggerDefinition(parentItem: PlanTreeviewItem, swagger: Swagger, definition: any) {\r
         Object.getOwnPropertyNames(definition.properties).map(key => {\r
             const property = definition.properties[key];\r
             const value = `${parentItem.value}.[${key}]`;\r
             const propertyItem = new PlanTreeviewItem(key, value, []);\r
             parentItem.children.push(propertyItem);\r
 \r
+            // reference to swagger.ts function getSchemaObject()\r
             if (property instanceof SwaggerReferenceObject) {\r
-                const propertyDefinition = this.configService.getDefinition(swagger, property.$ref);\r
-                this.loadParamsBySwaggerDefinition(propertyItem, swagger,\r
-                    <SwaggerModelSimple>propertyDefinition);\r
+                // handle reference parameter.\r
+                const propertyDefinition = this.restService.getDefinition(swagger, property.$ref);\r
+                this.loadParamsBySwaggerDefinition(propertyItem, swagger, propertyDefinition);\r
+            } else if (property instanceof SwaggerModelSimple) {\r
+                // handle object parameter.\r
+                this.loadParamsBySwaggerDefinition(propertyItem, swagger, property);\r
+            } else {\r
+                // skip\r
             }\r
 \r
             return propertyItem;\r
         });\r
     }\r
 \r
+    private createStatusCodeTreeViewItem(nodeId: string): PlanTreeviewItem {\r
+        return new PlanTreeviewItem('statusCode', `[${nodeId}].[statusCode]`, []);\r
+    }\r
+\r
+    private createResponseTreeViewItem(nodeId: string): PlanTreeviewItem {\r
+        return new PlanTreeviewItem('response', `[${nodeId}].[responseBody]`, []);\r
+    }\r
+\r
     public getPreNodes(nodeId: string, preNodes: WorkflowNode[]) {\r
         const preNode4CurrentNode = [];\r
         this.getProcess().forEach(node => {\r
@@ -201,7 +386,7 @@ export class ModelService {
     }\r
 \r
     public isPreNode(preNode: WorkflowNode, id: string): boolean {\r
-        const targetNode = preNode.sequenceFlows.find(connection => connection.targetRef === id);\r
+        const targetNode = preNode.connection.find(connection => connection.targetRef === id);\r
         return targetNode !== undefined;\r
     }\r
 \r
@@ -210,15 +395,62 @@ export class ModelService {
     }\r
 \r
     private createId() {\r
-        const idSet = new Set();\r
-        this.getProcess().forEach(node => idSet.add(node.id));\r
+        const nodeMap = this.getNodeMap();\r
 \r
-        for (let i = 0; i < idSet.size; i++) {\r
-            if (!idSet.has('node' + i)) {\r
-                return 'node' + i;\r
+        for (let i = 0; i < nodeMap.size; i++) {\r
+            const key = 'node' + i;\r
+            if (!nodeMap.get(key)) {\r
+                return key;\r
             }\r
         }\r
 \r
-        return 'node' + idSet.size;\r
+        return 'node' + nodeMap.size;\r
+    }\r
+\r
+    public getChildrenNodes(parentId: string): WorkflowNode[] {\r
+        if (!parentId || parentId === this.rootNodeId) {\r
+            return this.planModel.nodes;\r
+        } else {\r
+            const node = this.getNodeMap().get(parentId);\r
+            if (node.type === 'subProcess') {\r
+                return (<SubProcess>node).children;\r
+            } else {\r
+                return [];\r
+            }\r
+        }\r
+    }\r
+\r
+    public changeParent(id: string, originalParentId: string, targetParentId: string) {\r
+        if (originalParentId === targetParentId) {\r
+            return;\r
+        }\r
+\r
+        const node: WorkflowNode = this.deleteNode(originalParentId, id);\r
+        node.parentId = targetParentId;\r
+\r
+        if (targetParentId) {\r
+            this.addChild(targetParentId, node);\r
+        } else {\r
+            this.planModel.nodes.push(node);\r
+        }\r
+    }\r
+\r
+    public updatePosition(id: string, left: number, top: number, width: number, height: number) {\r
+        const node = this.getNodeMap().get(id);\r
+        node.position.left = left;\r
+        node.position.top = top;\r
+        node.position.width = width;\r
+        node.position.height = height;\r
+    }\r
+\r
+    public isDescendantNode(node: WorkflowNode, descendantId: string): boolean {\r
+        if (NodeType[NodeType.subProcess] !== node.type) {\r
+            return false;\r
+        }\r
+        const tmp = (<SubProcess>node).children.find(child => {\r
+            return child.id === descendantId || (NodeType[NodeType.subProcess] === child.type && this.isDescendantNode(<SubProcess>child, descendantId));\r
+        });\r
+\r
+        return tmp !== undefined;\r
     }\r
 }\r
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 (file)
index 0000000..db69d78
--- /dev/null
@@ -0,0 +1,168 @@
+/*******************************************************************************\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ *******************************************************************************/\r
+\r
+import { Injectable } from '@angular/core';\r
+import { Http, RequestOptionsArgs } from '@angular/http';\r
+import { Observable } from 'rxjs/Rx';\r
+import { isNullOrUndefined } from 'util';\r
+\r
+import { SwaggerMethod } from '../model/swagger';\r
+import { SwaggerResponse } from '../model/swagger';\r
+import { Swagger, SwaggerSchemaObject } from '../model/swagger';\r
+import { RestConfig } from '../model/rest-config';\r
+import { HttpService } from '../util/http.service';\r
+import { BroadcastService } from './broadcast.service';\r
+\r
+@Injectable()\r
+export class RestService {\r
+\r
+    private restConfigs: RestConfig[] = [];\r
+    private runtimeURL = '/openoapi/catalog/v1/sys/config';\r
+    private msbPublishServiceURL = '/api/msdiscover/v1/publishservicelist';\r
+\r
+    constructor(private broadcastService: BroadcastService, private http: Http) {\r
+        // this.initSwaggerInfoByMSB();\r
+    }\r
+\r
+    // public addRestConfig(): RestConfig {\r
+    //     let index = 0;\r
+    //     this.restConfigs.forEach(config => {\r
+    //         const currentId = parseInt(config.id);\r
+    //         if (currentId > index) {\r
+    //             index = currentId;\r
+    //         }\r
+    //     });\r
+\r
+    //     index += 1;\r
+\r
+    //     const restConfig = new RestConfig(index.toString(), 'new Config', '', '', false);\r
+    //     this.restConfigs.push(restConfig);\r
+\r
+    //     return restConfig;\r
+    // }\r
+\r
+    // public initSwaggerInfo(restConfig: RestConfig) {\r
+    //     if (restConfig.dynamic && restConfig.definition) {\r
+    //         this.getDynamicSwaggerInfo(restConfig.definition).subscribe(response => restConfig.swagger = new Swagger(response));\r
+    //     } else {\r
+    //         restConfig.swagger = new Swagger(restConfig.swagger);\r
+    //     }\r
+    // }\r
+\r
+    public getRestConfigs() {\r
+        return this.restConfigs;\r
+    }\r
+\r
+    // public getDynamicSwaggerInfo(url: string): Observable<any> {\r
+    //     const options: any = {\r
+    //         headers: {\r
+    //             Accept: 'application/json',\r
+    //         },\r
+    //     };\r
+    //     return this.httpService.get(url, options);\r
+    // }\r
+\r
+    public getSwaggerInfo(id: string): Swagger {\r
+        const restConfig = this.restConfigs.find(tmp => tmp.id === id);\r
+        return restConfig === undefined ? undefined : restConfig.swagger;\r
+    }\r
+\r
+    public getResponseParameters(swagger: Swagger, interfaceUrl: string, operation: string): SwaggerResponse[] {\r
+        const path = swagger.paths[interfaceUrl];\r
+        const method: SwaggerMethod = path[operation];\r
+        let responses: SwaggerResponse[] = [];\r
+\r
+        for (const key of Object.keys(method.responses)) {\r
+            if (key.startsWith('20') && method.responses[key].schema && method.responses[key].schema.$ref) {\r
+                let response: SwaggerResponse = method.responses[key];\r
+                responses.push(response);\r
+            }\r
+        }\r
+\r
+        return responses;\r
+    }\r
+\r
+    public getDefinition(swagger: Swagger, position: string): SwaggerSchemaObject {\r
+        const definitionName = position.substring('#/definitions/'.length);\r
+\r
+        return swagger.definitions[definitionName];\r
+    }\r
+\r
+    private initSwaggerInfoByMSB(): void {\r
+        const options: any = {\r
+            headers: {\r
+                Accept: 'application/json',\r
+            }\r
+        };\r
+        let restConfigs = this.restConfigs;\r
+        this.http.get(this.runtimeURL).subscribe(runtimeResponse => {\r
+            const tenant = runtimeResponse.json().tenant;\r
+            console.log('Current namespace is:' + tenant);\r
+            this.http.get(this.msbPublishServiceURL, { params: { namespace: tenant } }).subscribe(serviceResponse => {\r
+                if (!Array.isArray(serviceResponse.json())) {\r
+                    return;\r
+                }\r
+                const services = serviceResponse.json();\r
+                const protocel = location.protocol.slice(0, location.protocol.length - 1);\r
+                const swaggerObservableArray: Observable<any>[] = [];\r
+                services.forEach(serviceInfo => {\r
+                    if ('REST' === serviceInfo.protocol && protocel === serviceInfo.publish_protocol) {\r
+                        // this service don't have sawgger file.\r
+                        if ('/activiti-rest' !== serviceInfo.publish_url) {\r
+                            const id = serviceInfo.serviceName + '.' + serviceInfo.version;\r
+                            restConfigs.push(new RestConfig(id, serviceInfo.serviceName, serviceInfo.version, serviceInfo.publish_url));\r
+                            let swaggerUrl = '';\r
+                            if (undefined !== serviceInfo.swagger_url && '' !== serviceInfo.swagger_url) {\r
+                                swaggerUrl = serviceInfo.publish_url + '/' + serviceInfo.swagger_url;\r
+                            } else {\r
+                                // default swagger url is: '/swagger.json'\r
+                                swaggerUrl = serviceInfo.publish_url + '/swagger.json';\r
+                            }\r
+                            swaggerObservableArray.push(this.http.get(swaggerUrl, options).timeout(5000).catch((error): Observable<any> => {\r
+                                console.log('Request swagger from:"' + swaggerUrl + '" faild!');\r
+                                return Observable.of(null);\r
+                            }));\r
+                        }\r
+                    }\r
+                });\r
+                Observable.forkJoin(swaggerObservableArray).subscribe(\r
+                    responses => {\r
+                        let deleteArray: number[] = [];\r
+                        responses.forEach((response, index) => {\r
+                            // mark http get failed request index or set the swagger into restConfigs\r
+                            if (null === response) {\r
+                                deleteArray.push(index);\r
+                            } else {\r
+                                try {\r
+                                    const swagger = response.json();\r
+                                    restConfigs[index].swagger = new Swagger(swagger);\r
+                                } catch (e) {\r
+                                    deleteArray.push(index);\r
+                                    console.warn('Do not support this sawgger file format:' + response.text());\r
+                                }\r
+                            }\r
+                        });\r
+                        console.log('Get all swagger file finish.');\r
+                        // delete failed request from all restConfigs array\r
+                        deleteArray.reverse();\r
+                        deleteArray.forEach(deleteIndex => {\r
+                            restConfigs.splice(deleteIndex, 1);\r
+                        });\r
+                        this.broadcastService.broadcast(this.broadcastService.updateModelRestConfig, restConfigs);\r
+                        console.log('Load all swagger finished.');\r
+                    }\r
+                );\r
+            });\r
+        });\r
+    }\r
+}\r
+\r
index aba8aa2..7538226 100644 (file)
@@ -41,7 +41,7 @@ export class WorkflowService {
             }\r
             this.broadcastWorkflows();\r
         });\r
-        this.broadcastService.workflow.subscribe(workflow => this.planModel = workflow);\r
+        this.broadcastService.planModel.subscribe(workflow => this.planModel = workflow);\r
     }\r
 \r
     public save(): Observable<boolean> {\r