diff options
Diffstat (limited to 'sdc-workflow-designer-ui/src')
51 files changed, 1970 insertions, 919 deletions
diff --git a/sdc-workflow-designer-ui/src/app/app.component.css b/sdc-workflow-designer-ui/src/app/app.component.css index fdafa45c..95166937 100644 --- a/sdc-workflow-designer-ui/src/app/app.component.css +++ b/sdc-workflow-designer-ui/src/app/app.component.css @@ -9,19 +9,86 @@ * Contributors:
* ZTE - initial API and implementation and/or initial documentation
*/
- .main-content-wrapper{
+ .loading-div{
+ position: absolute;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background-color: white;
+}
+
+.loading-div div{
+ position: relative;
+ top: calc(50% - 36px);
+ left: calc(50% - 36px);
+}
+
+.loading-div div:not(:required) {
+ -moz-animation: three-quarters-loader 1.5s infinite linear;
+ -webkit-animation: three-quarters-loader 1.5s infinite linear;
+ animation: three-quarters-loader 1.5s infinite linear;
+ box-sizing: border-box;
+ display: inline-block;
+ overflow: hidden;
+ text-indent: -9999px;
+ border: 5px solid #1dadfc;
+ border-right-color: transparent;
+ border-radius: 36px;
+ width: 72px;
+ height: 72px;
+}
+
+@-moz-keyframes three-quarters-loader {
+ 0% {
+ -moz-transform: rotate(0deg);
+ transform: rotate(0deg)
+ }
+ to {
+ -moz-transform: rotate(1turn);
+ transform: rotate(1turn)
+ }
+}
+
+@-webkit-keyframes three-quarters-loader {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg)
+ }
+ to {
+ -webkit-transform: rotate(1turn);
+ transform: rotate(1turn)
+ }
+}
+
+@keyframes three-quarters-loader {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg)
+ }
+ to {
+ -moz-transform: rotate(1turn);
+ -ms-transform: rotate(1turn);
+ -webkit-transform: rotate(1turn);
+ transform: rotate(1turn)
+ }
+}
+
+.main-content-wrapper{
height: 100%;
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMTEgMTEiPjxkZWZzPjxzdHlsZT4uY2xzLTF7aXNvbGF0aW9uOmlzb2xhdGU7fS5jbHMtMntmaWxsOiNmYWZiZmQ7fS5jbHMtM3tmaWxsOiNlY2VkZWY7ZmlsbC1ydWxlOmV2ZW5vZGQ7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5iYWNrZ3JvdW5kLWltYWdlc192MjwvdGl0bGU+PGc+PGltYWdlIHdpZHRoPSIxMSIgaGVpZ2h0PSIxMSIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBc0FBQUFMQ0FJQUFBQW16dUJ4QUFBQUNYQklXWE1BQUFzU0FBQUxFZ0hTM1g3OEFBQUFFMGxFUVZRWVYyUDRUd2d3RUZJd3FvSmtGUUF3eFdtbDRtUGRyd0FBQUFCSlJVNUVya0pnZ2c9PSIvPjwvZz48ZyBpZD0i55+p5b2iXzEiIGRhdGEtbmFtZT0i55+p5b2iIDEiIGNsYXNzPSJjbHMtMSI+PGcgaWQ9IuefqeW9ol8xLTIiIGRhdGEtbmFtZT0i55+p5b2iIDEiPjxyZWN0IGNsYXNzPSJjbHMtMiIgd2lkdGg9IjExIiBoZWlnaHQ9IjExIi8+PC9nPjwvZz48ZyBjbGFzcz0iY2xzLTEiPjxnPjxwb2x5Z29uIGNsYXNzPSJjbHMtMyIgcG9pbnRzPSIxMCAwIDEwIDEwIDAgMTAgMCAxMSAxMCAxMSAxMC45MiAxMSAxMC45MiAwIDEwIDAiLz48L2c+PC9nPjwvc3ZnPg==);
background-size: 11px;
}
-.toolbar{
+.tool-bar{
position: fixed;
top: 0px;
left: 0px;
width: 200px;
height: 100%;
background-color: white;
+ overflow-y: auto;
}
.design-area{
@@ -32,7 +99,7 @@ padding: 20px;
}
-.design-menu{
+.design-menus{
display: block;
height: 30px;
margin-bottom: 10px;
diff --git a/sdc-workflow-designer-ui/src/app/app.component.html b/sdc-workflow-designer-ui/src/app/app.component.html index 1917b835..9f0e5cf2 100644 --- a/sdc-workflow-designer-ui/src/app/app.component.html +++ b/sdc-workflow-designer-ui/src/app/app.component.html @@ -11,13 +11,10 @@ * 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> diff --git a/sdc-workflow-designer-ui/src/app/app.module.ts b/sdc-workflow-designer-ui/src/app/app.module.ts index 199bfcdf..07ccebc0 100644 --- a/sdc-workflow-designer-ui/src/app/app.module.ts +++ b/sdc-workflow-designer-ui/src/app/app.module.ts @@ -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 index 1cf197df..00000000 --- a/sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.ts +++ /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/canvas/canvas.component.css b/sdc-workflow-designer-ui/src/app/components/container/container.component.css index bc889652..bc889652 100644 --- a/sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.css +++ b/sdc-workflow-designer-ui/src/app/components/container/container.component.css 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 index 00000000..0d9c5222 --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/components/container/container.component.html @@ -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 index 00000000..f35c2482 --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/components/container/container.component.ts @@ -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 index 00000000..78475cfa --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.css @@ -0,0 +1,26 @@ +/**
+ * 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
+ */
+
+ .edit{
+ font-size: 24px;
+ width: 300px;
+ height: 30px;
+ border: 1px solid #fff;
+}
+
+.edit:hover{
+ border-color: #80bdff;
+}
+
+.edit:focus{
+ border-color: #80bdff;
+}
diff --git a/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.html b/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.html index a2d9fd51..8dde9f1c 100644 --- a/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.html +++ b/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.html @@ -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> diff --git a/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.ts b/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.ts index 719d2a60..ea965755 100644 --- a/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/editable-property/editable-property.component.ts @@ -10,41 +10,44 @@ * 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); } } diff --git a/sdc-workflow-designer-ui/src/app/components/menu/menu.component.css b/sdc-workflow-designer-ui/src/app/components/menu/menus.component.css index 6ba4133b..6ba4133b 100644 --- a/sdc-workflow-designer-ui/src/app/components/menu/menu.component.css +++ b/sdc-workflow-designer-ui/src/app/components/menu/menus.component.css diff --git a/sdc-workflow-designer-ui/src/app/components/menu/menu.component.html b/sdc-workflow-designer-ui/src/app/components/menu/menus.component.html index 8cf9dc57..8cf9dc57 100644 --- a/sdc-workflow-designer-ui/src/app/components/menu/menu.component.html +++ b/sdc-workflow-designer-ui/src/app/components/menu/menus.component.html diff --git a/sdc-workflow-designer-ui/src/app/components/menu/menu.component.spec.ts b/sdc-workflow-designer-ui/src/app/components/menu/menus.component.spec.ts index b80edce7..b80edce7 100644 --- a/sdc-workflow-designer-ui/src/app/components/menu/menu.component.spec.ts +++ b/sdc-workflow-designer-ui/src/app/components/menu/menus.component.spec.ts diff --git a/sdc-workflow-designer-ui/src/app/components/menu/menu.component.ts b/sdc-workflow-designer-ui/src/app/components/menu/menus.component.ts index adad16c1..6932e764 100644 --- a/sdc-workflow-designer-ui/src/app/components/menu/menu.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/menu/menus.component.ts @@ -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() { diff --git a/sdc-workflow-designer-ui/src/app/components/node/node.component.css b/sdc-workflow-designer-ui/src/app/components/node/node.component.css index 093892e4..af1ce88e 100644 --- a/sdc-workflow-designer-ui/src/app/components/node/node.component.css +++ b/sdc-workflow-designer-ui/src/app/components/node/node.component.css @@ -11,30 +11,23 @@ */
.node {
- border: 1px solid transparent;
cursor: pointer;
display: inline-block;
position: absolute;
z-index: 2;
}
+.node-icon{
+ border-radius: 4px;
+}
-.node.active {
- border: 2px solid red !important;
- box-shadow: 2px 2px 19px #444;
- -o-box-shadow: 2px 2px 19px #444;
- -webkit-box-shadow: 2px 2px 19px #444;
- -moz-box-shadow: 2px 2px 19px #fff;
- opacity: 0.9;
+.node-icon svg{
+ display: block;
+ fill: #00ABFF;
}
-.node:hover {
- border: 1px solid #123456;
- box-shadow: 2px 2px 19px #444;
- -o-box-shadow: 2px 2px 19px #444;
- -webkit-box-shadow: 2px 2px 19px #444;
- -moz-box-shadow: 2px 2px 19px #fff;
- opacity: 0.9;
+.active {
+ outline: 1px solid #00ABFF;
}
/**
@@ -43,11 +36,10 @@ .anchors {
position: absolute;
border-radius: 1em;
- z-index: 20;
display: none;
- background-color: black;
- width: 0;
- height: 0;
+ background-color: #2e6f9a;
+ width: 12px;
+ height: 12px;
cursor: pointer;
-ms-transition: all 0.15s ease-in-out;
transition: all 0.15s ease-in-out;
@@ -56,35 +48,31 @@ -o-transition: all 0.15s ease-in-out;
}
-.node:hover .anchors {
- background-color: black;
+.node-icon:hover > .anchors {
display: inline-block;
- width: 12px;
- height: 12px;
- z-index: 20;
}
.anchor-left {
- left: -5px;
- top: 40%;
+ left: -6px;
+ top: calc(50%);
}
.anchor-right {
- right: -5px;
- top: 40%;
+ right: -6px;
+ top: calc(50%);
}
.anchor-top {
- top: -5px;
- left: 40%;
+ top: -6px;
+ left: calc(50% - 6px);
}
.anchor-bottom {
- bottom: -5px;
- left: 40%;
+ bottom: -6px;
+ left: calc(50% - 6px);
}
-/*right-arrow*/
+/*right arrow*/
.right {
width: 10px;
height: 10px;
@@ -104,7 +92,7 @@ border-top: 5px transparent dashed;
border-right: 5px transparent dashed;
border-bottom: 5px transparent dashed;
- border-left: 5px black solid;
+ border-left: 5px #2e6f9a solid;
overflow: hidden;
}
@@ -117,7 +105,7 @@ left: -2px;
}
-/*left-arrow*/
+/*left arrow */
.left {
width: 10px;
height: 10px;
@@ -134,11 +122,11 @@ position: absolute;
left: 0;
top: 0;
- z-index: 5;
+ z-index: 5; /*ie8-*/
border-top: 5px transparent dashed;
border-left: 5px transparent dashed;
border-bottom: 5px transparent dashed;
- border-right: 5px black solid;
+ border-right: 5px #2e6f9a solid;
overflow: hidden;
}
@@ -150,10 +138,10 @@ left: 2px;
}
-/*top-arrow*/
+/*top arrow*/
.top {
- width: 9px;
- height: 9px;
+ width: 10px;
+ height: 10px;
position: absolute;
left: 1px;
z-index: 2;
@@ -167,7 +155,7 @@ left: 0;
top: 0;
z-index: 5;
- border-bottom: 5px black solid;
+ border-bottom: 5px #2e6f9a solid;
border-left: 5px transparent dashed;
border-right: 5px transparent dashed;
border-top: 5px transparent dashed;
@@ -180,13 +168,13 @@ .top-arrow2 {
top: -2px;
- border-bottom: 4px white solid;
+ border-bottom: 5px white solid;
}
-/*bottom-arrow*/
+/*bottom arrow*/
.bottom {
- width: 9px;
- height: 9px;
+ width: 10px;
+ height: 10px;
position: absolute;
left: 1px;
top: 4px;
@@ -201,10 +189,10 @@ left: 0;
top: 0;
z-index: 5;
- border-bottom: 4px transparent dashed;
- border-left: 4px transparent dashed;
- border-right: 4px transparent dashed;
- border-top: 4px black solid;
+ border-bottom: 5px transparent dashed;
+ border-left: 5px transparent dashed;
+ border-right: 5px transparent dashed;
+ border-top: 5px #2e6f9a solid;
overflow: hidden;
}
@@ -214,77 +202,27 @@ }
.bottom-arrow2 {
- border-top: 4px white solid;
+ border-top: 5px white solid;
}
+/**
+ * Anchors End
+ */
.node .name {
- padding: 10px 15px;
-}
-
-.node:hover {
- border: 1px dotted #000;
-}
-
-.node.focus {
- border: 1px dotted red;
-}
-
-.startEvent {
- border-radius: 30px;
- border: 1px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px;
- width: 30px;
- /*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=");*/
-}
-
-.endEvent {
- border-radius: 30px;
- border: 2px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px;
- width: 30px;
- /*background-image: url("data:image/png;base64,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");*/
-}
-
-.intermediateCatchEvent {
- border-radius: 30px;
- border: 1px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px;
- width: 30px;
- 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>");
-}
-
-
-.scriptTask {
- border-radius: 8px;
- border: 2px solid rgb(0, 0, 0);
- height: 60px;
- width: 80px;
- 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> ");
-}
-
-.restTask {
- border-radius: 8px;
- border: 2px solid rgb(0, 0, 0);
- font-size: 10px;
+ width: 55px;
+ height: 12px;
+ text-align: center;
+ white-space: nowrap;
+ color: #5c6d90;
+ line-height: 12px;
+ cursor: pointer;
+ font-family: Arial;
+ font-size: 12px;
}
-.parallelGateway {
- transform: rotate(45deg);
- border: 2px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px;
- width: 30px;
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuND6NzHYAAAEASURBVGhD7ZXRDcIwDEQ7AiMwQkdiQ0ZgBEbpCCWRiBRVob5zbaDSIeUD9WzfvSruNOknAiIgAiIgAiIgAiIgAiLwQwKXMvtezkx48NQQ7XFpNfIsZy1nAUN4anBHhLI3UgMgITw1hCVOOjKzF4LVc26catQUqnPaOFZmmbOeH5seVL1nsl3ydk+QuxJki2vzKURv/G/Nt6hWCHTVcuiC1df3St2Sr/9vwbPC2536DVjm0Y9dOFWk4am3kLXnrecIoDQNag7VpRkdNWZNsfr0MCND1p731KQG6Q1Z5kcfO7QmPcSjTJiJKTU4W0O0l1QEREAEREAEREAEREAEvkHgBRtRrTMkpctqAAAAAElFTkSuQmCC");
+.resizeable {
+ background-color: darkolivegreen;
+ border:1px solid blue;
+ margin: 10px;
}
-.exclusiveGateway {
- transform: rotate(45deg);
- border: 2px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px;
- width: 30px;
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuND6NzHYAAAC4SURBVGhD7ZXRCcAgEEMdpSN0hI7WTTpKR+hIrZ9yIBi4SIUn+CGc0bwoVwoDAhCAAAQgAAEIQMBB4K6i7dwdhzg13yrezsN5mEMbAw6qiiYJKLQctSTgoKpokoBCS6mNHba3jgk8oTP39tk7drxY9tresbMvPP2vLG/grG95ZEaj1+C+TfmQztrpTyPbDAayiap6JKASy64ngWyiqh4JqMSy62O3/k2HzTaKHgQgAAEIQAACyxL4AOr3u2BKXQ3gAAAAAElFTkSuQmCC");
-}
diff --git a/sdc-workflow-designer-ui/src/app/components/node/node.component.html b/sdc-workflow-designer-ui/src/app/components/node/node.component.html index d4c59d68..1832944b 100644 --- a/sdc-workflow-designer-ui/src/app/components/node/node.component.html +++ b/sdc-workflow-designer-ui/src/app/components/node/node.component.html @@ -11,15 +11,15 @@ * ZTE - initial API and implementation and/or initial documentation
*/
-->
-<div (dblclick)="showProperties($event)" class="node {{node.type}}" id="{{node.id}}"
- (click)="onSelected()"
- [class.active]="active"
- [style.top]="node.position.top + 'px'"
- [style.left]="node.position.left + 'px'">
- <div class="name">
- {{getDisplayName()}}
- </div>
+<div (click)="onClick($event)" (mousedown)="onMousedown()" (dblclick)="showProperties($event)" class="node" id="{{node.id}}"
+(mouseover)="onMouseOver($event, $event.target.parentNode)" (mouseout)="onMouseOut($event, $event.target.parentNode)" [style.top]="node.position.top + 'px'"
+[style.left]="node.position.left + 'px'" [style.width]="node.position.width + 'px'" #nodeItem>
+
+<div class="name">{{node.name}}</div>
+<div *ngIf="canHaveChildren()" b4tResizable class="node-icon" [style.width]="node.position.width + 'px'" [style.height]="node.position.height + 'px'"
+ [class.active]="active">
+ <b4t-node *ngFor="let child of node.children" [node]="child" [rank]="rank + 10"></b4t-node>
<div class="anchor anchors anchor-left">
<span class="left">
<i class="left-arrow1"></i>
@@ -32,16 +32,118 @@ <i class="right-arrow2"></i>
</span>
</div>
- <div class="anchor anchors anchor-top">
- <span class="top">
- <i class="top-arrow1"></i>
- <i class="top-arrow2"></i>
+</div>
+
+<div *ngIf="!canHaveChildren()" class="node-icon" [class.active]="active">
+ <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'">
+ <g [ngSwitch]="node.type">
+ <g *ngSwitchCase="nodeType[nodeType.startEvent]">
+ <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
+ s15-6.7,15-15S23.3,0,15,0L15,0z" />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.endEvent]">
+ <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
+ s15-6.7,15-15S23.3,0,15,0L15,0z" />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.errorStartEvent]">
+ <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
+ s13,5.8,13,13S22.2,28,15,28z" />
+ <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
+ 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
+ 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
+ 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"
+ />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.errorEndEvent]">
+ <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
+ s11,4.9,11,11S21.1,26,15,26z" />
+ <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
+ 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
+ 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" />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.toscaNodeManagementTask]">
+ <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
+ 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" />
+ <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" />
+ <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" />
+ <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" />
+ <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
+ C25.7,15.5,25.2,15.1,24.7,15.1z" />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.restTask]">
+ <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
+ 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" />
+ <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" />
+ <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" />
+ <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" />
+ <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
+ 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
+ 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"
+ />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.exclusiveGateway]">
+ <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
+ 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"
+ />
+ <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
+ 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
+ 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
+ c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.parallelGateway]">
+ <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
+ s1-0.4,1-1V16h4.5c0.6,0,1-0.4,1-1S21.1,14,20.5,14z" />
+ <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
+ 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
+ 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
+ c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.subProcess]">
+ <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
+ 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
+ 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" />
+ <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
+ 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" />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.intermediateCatchEvent]">
+ <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
+ 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
+ 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"
+ />
+ <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
+ c0.2,0.3,0.5,0.4,0.8,0.4h5c0.6,0,1-0.4,1-1S20.6,14,20,14z" />
+ </g>
+ <g *ngSwitchCase="nodeType[nodeType.scriptTask]">
+ <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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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" />
+ <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
+ l3.6-3.6C17.5,13.1,17.5,12.7,17.2,12.4z" />
+ <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
+ 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" />
+ <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
+ c0.1,0.1,0.3,0.2,0.5,0.2S17,20.7,17.1,20.6z" />
+ </g>
+ </g>
+ </svg>
+ <div class="anchor anchors anchor-left">
+ <span class="left">
+ <i class="left-arrow1"></i>
+ <i class="left-arrow2"></i>
</span>
</div>
- <div class="anchor anchors anchor-bottom">
- <span class="bottom">
- <i class="bottom-arrow1"></i>
- <i class="bottom-arrow2"></i>
+ <div class="anchor anchors anchor-right">
+ <span class="right">
+ <i class="right-arrow1"></i>
+ <i class="right-arrow2"></i>
</span>
</div>
</div>
+</div>
diff --git a/sdc-workflow-designer-ui/src/app/components/node/node.component.ts b/sdc-workflow-designer-ui/src/app/components/node/node.component.ts index 5fe189db..e688e973 100644 --- a/sdc-workflow-designer-ui/src/app/components/node/node.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/node/node.component.ts @@ -9,16 +9,19 @@ * Contributors:
* ZTE - initial API and implementation and/or initial documentation
*/
+import { AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild } from '@angular/core';
-import { Component, AfterViewInit, Input, OnDestroy } from '@angular/core';
-
+import { Subscription } from 'rxjs/Subscription';
+import { SubProcess } from '../../model/workflow/sub-process';
+import { WorkflowNode } from '../../model/workflow/workflow-node';
+import { BroadcastService } from '../../services/broadcast.service';
import { JsPlumbService } from '../../services/jsplumb.service';
-import { BroadcastService } from "../../services/broadcast.service";
-import { WorkflowNode } from "../../model/workflow/workflow-node";
-import { Subscription } from "rxjs/Subscription";
+import { ModelService } from '../../services/model.service';
+import { NodeType } from '../../model/workflow/node-type.enum';
/**
- * workflow node component
+ * node component represent a single workflow node.
+ * every node would be rendered on the container component
*/
@Component({
selector: 'b4t-node',
@@ -26,61 +29,85 @@ import { Subscription } from "rxjs/Subscription"; templateUrl: 'node.component.html',
})
export class NodeComponent implements AfterViewInit, OnDestroy {
-
@Input() public node: WorkflowNode;
- @Input() public last: boolean;
+ @Input() public rank: number;
+ @ViewChild('nodeItem') nodeItem: ElementRef;
+ public nodeType = NodeType;
public active = false;
- private currentTypeSubscription: Subscription;
private currentWorkflowSubscription: Subscription;
+ private isMoving = false;
- constructor(private broadcastService: BroadcastService,
- private jsPlumbService: JsPlumbService) {
-
+ constructor(private jsPlumbService: JsPlumbService,
+ private modelService: ModelService,
+ private broadcastService: BroadcastService) {
}
- ngAfterViewInit(): void {
- if(this.last) {
- this.jsPlumbService.initNode();
- this.jsPlumbService.connectNodes();
- }
+ public ngAfterViewInit() {
+ this.jsPlumbService.initJsPlumbInstance(this.node.parentId);
+ this.jsPlumbService.initNode(this.node);
- this.currentTypeSubscription = this.broadcastService.currentType$.subscribe(type => {
- if (type === 'SequenceFlow') {
- this.active = false;
- }
- });
+ if (this.canHaveChildren()) {
+ this.jsPlumbService.nodeDroppable(this.node, this.rank);
+ this.jsPlumbService.connectChildrenNodes(this.node.id);
+ }
- this.currentWorkflowSubscription = this.broadcastService.currentWorkflowNode$.subscribe(activeNode => {
- if (activeNode.id === this.node.id) {
- this.active = true;
- } else {
- this.active = false;
+ this.currentWorkflowSubscription = this.broadcastService.selectedElement$.subscribe(activeNodes => {
+ let active = false;
+ for (let index = 0; index < activeNodes.length; index++) {
+ let activeNode = activeNodes[index] as WorkflowNode;
+ if (activeNode.id === this.node.id) {
+ active = true;
+ break;
+ }
}
+ this.active = active;
});
}
public ngOnDestroy() {
- this.currentTypeSubscription.unsubscribe();
this.currentWorkflowSubscription.unsubscribe();
+ if (this.nodeItem.nativeElement.onmousemove) {
+ this.nodeItem.nativeElement.onmousemove = null;
+ }
}
- public showProperties() {
- this.broadcastService.broadcast(this.broadcastService.nodeProperty, this.node);
- this.broadcastService.broadcast(this.broadcastService.showProperty, true);
+ public onMousedown() {
+ let currentThis = this;
+ this.nodeItem.nativeElement.onmousemove = function () {
+ currentThis.isMoving = true;
+ };
}
- public getDisplayName(): string {
- if (this.node.type === 'restTask' || this.node.type === 'toscaTask') {
- return this.node.name;
- } else {
- return ' ';
+ public onClick(event) {
+ if (this.nodeItem.nativeElement.onmousemove) {
+ this.nodeItem.nativeElement.onmousemove = null;
+ }
+ if (this.isMoving && this.active) {
+ this.isMoving = false;
+ return;
}
+ event.stopPropagation();
+ this.broadcastService.broadcast(this.broadcastService.showProperty, null);
+ this.broadcastService.broadcast(this.broadcastService.selectedElement, [this.node]);
+ }
+
+ public canHaveChildren(): boolean {
+ return this.node.type === 'subProcess';
}
- public onSelected() {
- this.broadcastService.broadcast(this.broadcastService.currentWorkflowNode, this.node);
- this.broadcastService.broadcast(this.broadcastService.currentType, 'WorkflowNode');
+ public onMouseOut(event, target) {
+ event.stopPropagation();
+ target.classList.remove('hover');
}
+ public onMouseOver(event, target) {
+ event.stopPropagation();
+ target.classList.add('hover');
+ }
+
+ public showProperties(event) {
+ event.stopPropagation();
+ this.broadcastService.broadcast(this.broadcastService.showProperty, this.node);
+ }
}
diff --git a/sdc-workflow-designer-ui/src/app/components/parameter-tree/parameter-tree.component.ts b/sdc-workflow-designer-ui/src/app/components/parameter-tree/parameter-tree.component.ts index 9271dac8..77da46b7 100644 --- a/sdc-workflow-designer-ui/src/app/components/parameter-tree/parameter-tree.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/parameter-tree/parameter-tree.component.ts @@ -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) { diff --git a/sdc-workflow-designer-ui/src/app/components/property/properties.component.html b/sdc-workflow-designer-ui/src/app/components/property/properties.component.html index 2870a4b1..19d0dce1 100644 --- a/sdc-workflow-designer-ui/src/app/components/property/properties.component.html +++ b/sdc-workflow-designer-ui/src/app/components/property/properties.component.html @@ -14,19 +14,12 @@ <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> diff --git a/sdc-workflow-designer-ui/src/app/components/property/properties.component.ts b/sdc-workflow-designer-ui/src/app/components/property/properties.component.ts index 2091d83c..d3a6a416 100644 --- a/sdc-workflow-designer-ui/src/app/components/property/properties.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/property/properties.component.ts @@ -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); } } diff --git a/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task-parameters/rest-task-parameters.component.ts b/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task-parameters/rest-task-parameters.component.ts index 7f8bbf43..8e8cc94f 100644 --- a/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task-parameters/rest-task-parameters.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task-parameters/rest-task-parameters.component.ts @@ -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); diff --git a/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task.component.ts b/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task.component.ts index d0c92dfd..eb1c81bd 100644 --- a/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/property/rest-task/rest-task.component.ts @@ -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]; - } } diff --git a/sdc-workflow-designer-ui/src/app/components/sequence-flow/sequence-flow.component.ts b/sdc-workflow-designer-ui/src/app/components/sequence-flow/sequence-flow.component.ts index c4a70ec9..b114d0ae 100644 --- a/sdc-workflow-designer-ui/src/app/components/sequence-flow/sequence-flow.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/sequence-flow/sequence-flow.component.ts @@ -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); } } diff --git a/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.css b/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.css index 3edffd66..1d119530 100644 --- a/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.css +++ b/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.css @@ -9,106 +9,54 @@ * Contributors:
* ZTE - initial API and implementation and/or initial documentation
*/
-
- .toolbar{
- padding: 20px 10px;
-}
-
-.row{
- margin: 0;
-}
-
-button {
- min-width: 40px;
- width: 60px;
- height: 60px;
- transition: all 0s;
- margin: 10px;
- padding: 0;
-}
-
-button div{
- left: 0;
- right: 0;
- margin: auto;
- width: 40px;
- height: 40px;
-}
-
-button span{
- padding: 0;
- font-size: 10px;
- letter-spacing: 0px;
- color: black;
+ .toolbar-head{
+ color:#404040;
+ font-size: 14px;
}
-.subProcess {
- border-radius: 8px;
- border: 2px solid rgb(0, 0, 0);
- font-size: 10px;
+.toolbar-head:hover{
+ cursor: pointer;
}
-.parallelGateway {
- transform: rotate(45deg);
- border: 2px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px !important;
- width: 30px !important;
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuND6NzHYAAAEASURBVGhD7ZXRDcIwDEQ7AiMwQkdiQ0ZgBEbpCCWRiBRVob5zbaDSIeUD9WzfvSruNOknAiIgAiIgAiIgAiIgAiLwQwKXMvtezkx48NQQ7XFpNfIsZy1nAUN4anBHhLI3UgMgITw1hCVOOjKzF4LVc26catQUqnPaOFZmmbOeH5seVL1nsl3ydk+QuxJki2vzKURv/G/Nt6hWCHTVcuiC1df3St2Sr/9vwbPC2536DVjm0Y9dOFWk4am3kLXnrecIoDQNag7VpRkdNWZNsfr0MCND1p731KQG6Q1Z5kcfO7QmPcSjTJiJKTU4W0O0l1QEREAEREAEREAEREAEvkHgBRtRrTMkpctqAAAAAElFTkSuQmCC");
+.fold-icon{
+ width: 15px;
+ font-size: 8px;
+ color: #00abff;
}
-.exclusiveGateway {
- transform: rotate(45deg);
- border: 2px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px !important;
- width: 30px !important;
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuND6NzHYAAAC4SURBVGhD7ZXRCcAgEEMdpSN0hI7WTTpKR+hIrZ9yIBi4SIUn+CGc0bwoVwoDAhCAAAQgAAEIQMBB4K6i7dwdhzg13yrezsN5mEMbAw6qiiYJKLQctSTgoKpokoBCS6mNHba3jgk8oTP39tk7drxY9tresbMvPP2vLG/grG95ZEaj1+C+TfmQztrpTyPbDAayiap6JKASy64ngWyiqh4JqMSy62O3/k2HzTaKHgQgAAEIQAACyxL4AOr3u2BKXQ3gAAAAAElFTkSuQmCC");
+.item{
+ width: 50px;
+ height: 50px;
+ text-align: center;
+ float: left;
+ margin-left: 6px;
+ margin-bottom: 10px;
}
-.startEvent {
- border-radius: 30px;
- border: 1px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px;
- width: 30px;
- /*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=");*/
+.item:hover{
+ cursor: pointer;
}
-.endEvent {
- border-radius: 30px;
- border: 2px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px;
- width: 30px;
- /*background-image: url("data:image/png;base64,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");*/
+.item svg{
+ width:24px;
+ height:24px;
+ margin: 4px 13px;
+ display: block;
+ /* fill: #A9B2BA; */
+ fill: #00ABFF;
}
-.intermediateCatchEvent {
- border-radius: 30px;
- border: 1px solid rgb(0, 0, 0);
- background-size: cover;
- height: 30px;
- width: 30px;
- 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>");
+.item span{
+ font-size: 12px;
+ color: #595959;
+ display: block;
}
-
-.scriptTask {
- background-size: cover;
- height: 30px;
- width: 30px;
- 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> ");
+.getway{
+ padding-top: 5px;
}
-.toscaTask {
- border-radius: 8px;
- border: 2px solid rgb(0, 0, 0);
- font-size: 10px;
-}
-
-.restTask {
- border-radius: 8px;
- border: 2px solid rgb(0, 0, 0);
- font-size: 10px;
+.getway div{
+ width: 30px !important;
+ height: 30px !important;
}
diff --git a/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.html b/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.html index bb52644f..382e195e 100644 --- a/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.html +++ b/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.html @@ -11,13 +11,184 @@ * ZTE - initial API and implementation and/or initial documentation
*/
-->
-<div class="toolbar">
- <div class="row">
- <button *ngFor="let nodeType of nodeTypes" type="button" [attr.nodeType]="nodeType"
- class="btn btn-secondary item ui-draggable">
- <div class="{{nodeType}}">
- </div>
- <span>{{getNameByType(nodeType)}}</span>
- </button>
- </div>
-</div>
+<accordion>
+ <accordion-group [isOpen]="true" #event>
+ <div accordion-heading class="toolbar-head">
+ <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': event?.isOpen, 'fa-chevron-right': !event?.isOpen}"></i>
+ <i class="fa fa-th-list"></i>
+ <span>EVENT</span>
+ </div>
+ <div nodeType="startEvent" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ s15-6.7,15-15S23.3,0,15,0L15,0z" />
+ </g>
+ </svg>
+ <span>Start</span>
+ </div>
+ <div nodeType="endEvent" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ s15-6.7,15-15S23.3,0,15,0L15,0z" />
+ </g>
+ </svg>
+ <span>End</span>
+ </div>
+ <div nodeType="intermediateCatchEvent" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ 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
+ 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"
+ />
+ <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
+ c0.2,0.3,0.5,0.4,0.8,0.4h5c0.6,0,1-0.4,1-1S20.6,14,20,14z" />
+ </g>
+ </svg>
+ <span>Timer</span>
+ </div>
+ <!--
+ <div nodeType="errorStartEvent" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ s13,5.8,13,13S22.2,28,15,28z" />
+ <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
+ 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
+ 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
+ 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"
+ />
+ </g>
+ </svg>
+ <span>{{ 'WORKFLOW.ERROR_START_EVENT' | translate }}</span>
+ </div>
+ <div nodeType="errorEndEvent" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ s11,4.9,11,11S21.1,26,15,26z" />
+ <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
+ 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
+ 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" />
+ </g>
+ </svg>
+ <span>{{ 'WORKFLOW.ERROR_END_EVENT' | translate }}</span>
+ </div>
+ -->
+ </accordion-group>
+ <accordion-group [isOpen]="true" #task>
+ <div accordion-heading class="toolbar-head">
+ <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': task?.isOpen, 'fa-chevron-right': !task?.isOpen}"></i>
+ <i class="fa fa-th-list"></i>
+ <span>Task</span>
+ </div>
+ <div *ngIf="!isCatalog" nodeType="toscaNodeManagementTask" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ 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" />
+ <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" />
+ <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" />
+ <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" />
+ <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
+ C25.7,15.5,25.2,15.1,24.7,15.1z" />
+ </g>
+ </svg>
+ <span>TOSCA</span>
+ </div>
+ <div *ngIf="isCatalog" nodeType="restTask" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ 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" />
+ <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" />
+ <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" />
+ <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" />
+ <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
+ 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
+ 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"
+ />
+ </g>
+ </svg>
+ <span>Rest</span>
+ </div>
+ <div nodeType="scriptTask" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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" />
+ <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
+ l3.6-3.6C17.5,13.1,17.5,12.7,17.2,12.4z" />
+ <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
+ 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" />
+ <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
+ c0.1,0.1,0.3,0.2,0.5,0.2S17,20.7,17.1,20.6z" />
+ </g>
+ </svg>
+ <span>Script</span>
+ </div>
+ </accordion-group>
+ <accordion-group [isOpen]="true" #getway>
+ <div accordion-heading class="toolbar-head">
+ <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': getway?.isOpen, 'fa-chevron-right': !getway?.isOpen}"></i>
+ <i class="fa fa-th-list"></i>
+ <span>Gateway</span>
+ </div>
+ <div nodeType="exclusiveGateway" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ 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"
+ />
+ <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
+ 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
+ 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
+ c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />
+ </g>
+ </svg>
+ <span>EXCLUSIVE</span>
+ </div>
+ <div nodeType="parallelGateway" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ s1-0.4,1-1V16h4.5c0.6,0,1-0.4,1-1S21.1,14,20.5,14z" />
+ <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
+ 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
+ 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
+ c0.2,0.2,0.3,0.4,0.3,0.7S27.9,15.5,27.7,15.7z" />
+ </g>
+ </svg>
+ <span>PARALLEL</span>
+ </div>
+ </accordion-group>
+ <!-- <accordion-group [isOpen]="true" #structural>
+ <div accordion-heading class="toolbar-head">
+ <i class="fa fold-icon" [ngClass]="{'fa-chevron-down': structural?.isOpen, 'fa-chevron-right': !structural?.isOpen}"></i>
+ <i class="fa fa-th-list"></i>
+ <span>{{ 'WORKFLOW.BPMN_STRUCTURAL' | translate }}</span>
+ </div>
+ <div nodeType="subProcess" class="item ui-draggable">
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <g>
+ <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
+ 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
+ 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"/>
+ <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
+ 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"/>
+ </g>
+ </svg>
+ <span>{{ 'WORKFLOW.SUB_PROCESS' | translate }}</span>
+ </div>
+ </accordion-group> -->
+</accordion>
diff --git a/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.ts b/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.ts index 71bf02ab..c204a19b 100644 --- a/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.ts +++ b/sdc-workflow-designer-ui/src/app/components/toolbar/toolbar.component.ts @@ -10,10 +10,10 @@ * ZTE - initial API and implementation and/or initial documentation
*/
-import { AfterViewInit, Component, OnInit } from '@angular/core';
+import { AfterViewChecked, Component, OnInit } from '@angular/core';
+import { BroadcastService } from '../../services/broadcast.service';
import { JsPlumbService } from '../../services/jsplumb.service';
-import { NodeType } from "../../model/workflow/node-type.enum";
/**
* toolbar component contains some basic operations(save) and all of the supported workflow nodes.
@@ -24,29 +24,20 @@ import { NodeType } from "../../model/workflow/node-type.enum"; templateUrl: 'toolbar.component.html',
styleUrls: ['./toolbar.component.css']
})
-export class ToolbarComponent implements AfterViewInit, OnInit {
- public nodeTypes = [];
+export class ToolbarComponent implements AfterViewChecked, OnInit {
+ public isCatalog = true;
+ private needInitButton = true;
- constructor(private jsPlumbService: JsPlumbService) {
- }
-
- public ngAfterViewInit() {
- this.jsPlumbService.buttonDraggable();
- }
+ constructor(private jsPlumbService: JsPlumbService, private broadcastService: BroadcastService) { }
- ngOnInit(): void {
- this.getNodeTypes();
+ public ngOnInit() {
}
- private getNodeTypes() {
- for(let key in NodeType) {
- if (typeof NodeType[key] === 'number') {
- this.nodeTypes.push(key);
- }
+ public ngAfterViewChecked() {
+ if (this.needInitButton) {
+ this.jsPlumbService.buttonDraggable();
+ this.jsPlumbService.buttonDroppable();
+ this.needInitButton = false;
}
}
-
- public getNameByType(type:string):string{
- return type.replace(type.charAt(0), type.charAt(0).toUpperCase());
- }
}
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 index 395cf040..00000000 --- a/sdc-workflow-designer-ui/src/app/directive/drag-select/drag-select.directive.ts +++ /dev/null @@ -1,134 +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, Directive, ElementRef } from '@angular/core';
-import { JsPlumbService } from "../../services/jsplumb.service";
-
-@Directive({
- selector: '[b4tDragSelect]'
-})
-export class DragSelectDirective implements AfterViewInit {
- private selectBox: any;
- public selecting = false;
-
- public relatvieX: number;
- public relatvieY: number;
-
- public startX: number;
- public startY: number;
- public endX: number;
- public endY: number;
-
- public left: number = 0;
- public top: number = 0;
- public width: number = 0;
- public height: number = 0;
-
- constructor(private el: ElementRef, private jsPlumbService: JsPlumbService) { }
-
- public ngAfterViewInit(): void {
- this.selectBox = document.createElement('div');
- const selectArea = this.el.nativeElement.appendChild(this.selectBox);
- this.el.nativeElement.addEventListener("mousedown", (event: MouseEvent) => this.mouseDown(event));
- this.el.nativeElement.addEventListener("mousemove", (event: MouseEvent) => this.mouseMove(event));
- this.el.nativeElement.addEventListener("mouseup", (event: MouseEvent) => this.mouseUp(event));
- }
-
- public mouseDown(event: MouseEvent) {
- this.relatvieX = event.clientX - event.offsetX;
- this.relatvieY = event.clientY - event.offsetY;
-
- this.width = 0;
- this.height = 0;
- this.startX = event.clientX;
- this.startY = event.clientY;
- this.endX = this.startX;
- this.endY = this.startY;
- this.selecting = true;
- this.updateSelectArea();
- }
-
- public mouseMove(event: MouseEvent) {
- this.endX = event.clientX;
- this.endY = event.clientY;
-
- this.updateSelectArea();
- }
-
- public mouseUp(event: MouseEvent) {
- this.selecting = false;
- this.updateSelectArea();
- }
-
- private updateSelectArea() {
- if (this.selecting) {
- this.selectBox.className = 'selecting';
- } else {
- this.selectBox.className = '';
- return;
- }
-
- this.getAllSelectedNodes();
-
- const leftTmp = this.startX >= this.endX ? this.endX : this.startX;
- const topTmp = this.startY >= this.endY ? this.endY : this.startY;
-
- this.left = leftTmp - this.relatvieX;
- this.top = topTmp - this.relatvieY;
-
- this.width = Math.abs(this.startX - this.endX);
- this.height = Math.abs(this.endY - this.startY);
-
- this.selectBox.style.top = this.top + 'px';
- this.selectBox.style.left = this.left + 'px';
- this.selectBox.style.width = this.width + 'px';
- this.selectBox.style.height = this.height + 'px';
- }
-
- public getAllSelectedNodes() {
- if(!this.selecting) {
- return;
- }
- const selectedNodes = [];
-
- const nodes = this.el.nativeElement.querySelectorAll('div.node');
- nodes.forEach(node => {
- if(this.checkNodeSelected(node)) {
- selectedNodes.push(node);
- }
- });
-
- this.jsPlumbService.jsplumbInstance.clearDragSelection();
- this.jsPlumbService.jsplumbInstance.addToDragSelection(selectedNodes);
-
- }
-
- private checkNodeSelected(node: any): boolean {
- const nodeLeft = node.offsetLeft;
- const nodeTop = node.offsetTop;
- const nodeRigth = nodeLeft + node.clientWidth;
- const nodeBottom = nodeTop + node.clientHeight;
-
- const selectedRight = this.left + this.width;
- const selectedBottom = this.top + this.height;
-
- return this.between(nodeLeft, this.left, selectedRight)
- && this.between(nodeRigth, this.left, selectedRight)
- && this.between(nodeTop, this.top, selectedBottom)
- && this.between(nodeBottom, this.top, selectedBottom);
- }
-
- private between(value, min, max): boolean {
- return min <= value && value <= max;
- }
-
-}
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 index 00000000..f591fe6f --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/directive/resizeable/resizable.directive.ts @@ -0,0 +1,42 @@ +/**
+ * 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, Directive, ElementRef } from '@angular/core';
+import * as $ from 'jquery';
+
+import { JsPlumbService } from '../../services/jsplumb.service';
+import { ModelService } from '../../services/model.service';
+
+@Directive({ selector: '[b4tResizable]' })
+export class ResizableDirective implements AfterViewInit {
+
+ constructor(private el: ElementRef,
+ private jsPlumbService: JsPlumbService,
+ private planModelService: ModelService) {
+ }
+
+ public ngAfterViewInit() {
+ console.log('init resizble.');
+
+ $(this.el.nativeElement).resizable({
+ handles: 'all',
+ resize: (event, ui) => {
+ const element = ui.helper[0];
+ this.planModelService.updatePosition(element.id,
+ element.offsetLeft, element.offsetTop, element.offsetWidth, element.offsetHeight - 12);
+ this.jsPlumbService.resizeParent(element, element.parentNode);
+ const node = this.planModelService.getNodeMap().get(element.id);
+ this.jsPlumbService.jsplumbInstanceMap.get(node.parentId).revalidate(element.id);
+ },
+ });
+ }
+}
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 index 00000000..42dc46b9 --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/model/rest-config.ts @@ -0,0 +1,17 @@ +/**
+ * 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 { Swagger } from './swagger';
+
+export class RestConfig {
+ constructor(public id: string, public name: string, public version: string, public url: string,
+ public swagger?: Swagger) { }
+}
diff --git a/sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.html b/sdc-workflow-designer-ui/src/app/model/topology/node-template.ts index daf26bc1..721ae604 100644 --- a/sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.html +++ b/sdc-workflow-designer-ui/src/app/model/topology/node-template.ts @@ -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> +/**
+ * 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
+ */
+
+export class NodeTemplate {
+ public id: string;
+ public name: string;
+ public type: string;
+ public namespace: string;
+}
diff --git a/sdc-workflow-designer-ui/src/app/model/value-source.enum.ts b/sdc-workflow-designer-ui/src/app/model/value-source.enum.ts index fd08c8de..f76f6591 100644 --- a/sdc-workflow-designer-ui/src/app/model/value-source.enum.ts +++ b/sdc-workflow-designer-ui/src/app/model/value-source.enum.ts @@ -13,7 +13,7 @@ export enum ValueSource { String, Plan, + Topology, Variable, Definition, - // Topology, // TODO implement Topology properties in R2 } diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/end-event.ts b/sdc-workflow-designer-ui/src/app/model/workflow/end-event.ts index 300af898..e3fbcad3 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/end-event.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/end-event.ts @@ -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 index 00000000..7285402a --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/model/workflow/error-event.ts @@ -0,0 +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
+ */
+import { ValueSource } from '../value-source.enum';
+import { Parameter } from './parameter';
+import { WorkflowNode } from './workflow-node';
+
+export interface ErrorEvent extends WorkflowNode {
+ parameter?: Parameter;
+}
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/intermediate-catch-event.ts b/sdc-workflow-designer-ui/src/app/model/workflow/intermediate-catch-event.ts index 13a3d1e0..653e627f 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/intermediate-catch-event.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/intermediate-catch-event.ts @@ -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; } diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/node-type.enum.ts b/sdc-workflow-designer-ui/src/app/model/workflow/node-type.enum.ts index 2481cdbb..22170c16 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/node-type.enum.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/node-type.enum.ts @@ -13,9 +13,13 @@ export enum NodeType { startEvent, endEvent, + errorStartEvent, + errorEndEvent, + toscaNodeManagementTask, restTask, - intermediateCatchEvent, exclusiveGateway, parallelGateway, - scriptTask, + subProcess, + intermediateCatchEvent, + scriptTask } diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/parameter.ts b/sdc-workflow-designer-ui/src/app/model/workflow/parameter.ts index cc87a6fa..67ca7f3f 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/parameter.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/parameter.ts @@ -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) { } } diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/rest-parameter.ts b/sdc-workflow-designer-ui/src/app/model/workflow/rest-parameter.ts index ecea3541..a7e4eeea 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/rest-parameter.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/rest-parameter.ts @@ -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); } } diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/rest-task.ts b/sdc-workflow-designer-ui/src/app/model/workflow/rest-task.ts index 2b3045df..12637d01 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/rest-task.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/rest-task.ts @@ -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[]; } diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/script-task.ts b/sdc-workflow-designer-ui/src/app/model/workflow/script-task.ts index 3772226c..392376ad 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/script-task.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/script-task.ts @@ -9,16 +9,9 @@ * Contributors:
* ZTE - initial API and implementation and/or initial documentation
*/
-import { Position } from './position';
import { WorkflowNode } from './workflow-node';
-import { SequenceFlow } from "./sequence-flow";
-
-export class ScriptTask extends WorkflowNode {
- public scriptFormat: string;
- public script: string;
-
- public constructor(public id: string, public name: string, public type: string, public position: Position, public sequenceFlows: SequenceFlow[]) {
- super(id, name, type, position, sequenceFlows);
- }
+export interface ScriptTask extends WorkflowNode {
+ scriptFormat: string;
+ script?: string;
}
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/start-event.ts b/sdc-workflow-designer-ui/src/app/model/workflow/start-event.ts index d609f7ca..a8f6444c 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/start-event.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/start-event.ts @@ -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 index 00000000..0da453e4 --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/model/workflow/sub-process.ts @@ -0,0 +1,15 @@ +/**
+ * 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 { WorkflowNode } from './workflow-node';
+export interface SubProcess extends WorkflowNode {
+ children?: WorkflowNode[];
+}
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/timer-event-definition.ts b/sdc-workflow-designer-ui/src/app/model/workflow/timer-event-definition.ts index f78d3973..101ef46c 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/timer-event-definition.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/timer-event-definition.ts @@ -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 index 00000000..986f0188 --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/model/workflow/tosca-node-task.ts @@ -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
+ */
+import { NodeTemplate } from '../topology/node-template';
+import { Parameter } from './parameter';
+import { WorkflowNode } from './workflow-node';
+
+export interface ToscaNodeTask extends WorkflowNode {
+ input?: Parameter[];
+ output?: Parameter[];
+ nodeInterface?: string;
+ operation?: string;
+ template?: NodeTemplate;
+}
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 index 00000000..9b0e2fe0 --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/model/workflow/workflow-element.ts @@ -0,0 +1,14 @@ +/**
+ * 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
+ */
+
+export interface WorkflowElement {
+}
diff --git a/sdc-workflow-designer-ui/src/app/model/workflow/workflow-node.ts b/sdc-workflow-designer-ui/src/app/model/workflow/workflow-node.ts index 9e54be13..628148a4 100644 --- a/sdc-workflow-designer-ui/src/app/model/workflow/workflow-node.ts +++ b/sdc-workflow-designer-ui/src/app/model/workflow/workflow-node.ts @@ -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; } diff --git a/sdc-workflow-designer-ui/src/app/services/broadcast.service.ts b/sdc-workflow-designer-ui/src/app/services/broadcast.service.ts index dd75c45c..544c2a70 100644 --- a/sdc-workflow-designer-ui/src/app/services/broadcast.service.ts +++ b/sdc-workflow-designer-ui/src/app/services/broadcast.service.ts @@ -15,6 +15,8 @@ import { Subject } from 'rxjs/Subject'; import { WorkflowNode } from '../model/workflow/workflow-node'; import { SequenceFlow } from "../model/workflow/sequence-flow"; import { PlanModel } from "../model/workflow/plan-model"; +import { WorkflowElement } from '../model/workflow/workflow-element'; +import { RestConfig } from '../model/rest-config'; /** * BroadcastService @@ -30,15 +32,21 @@ export class BroadcastService { public workflows = new Subject<Map<number, any>>(); public workflows$ = this.workflows.asObservable(); - public workflow = new Subject<PlanModel>(); - public workflow$ = this.workflow.asObservable(); + public planModel = new Subject<PlanModel>(); + public planModel$ = this.planModel.asObservable(); public showProperty = new Subject<boolean>(); public showProperty$ = this.showProperty.asObservable(); + public updateModelRestConfig = new Subject<RestConfig[]>(); + public updateModelRestConfig$ = this.updateModelRestConfig.asObservable(); + public saveEvent = new Subject<string>(); public saveEvent$ = this.saveEvent.asObservable(); + public selectedElement = new Subject<WorkflowElement[]>(); + public selectedElement$ = this.selectedElement.asObservable(); + public nodeProperty = new Subject<WorkflowNode>(); public nodeProperty$ = this.nodeProperty.asObservable(); diff --git a/sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts b/sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts index 084c0551..5b2750b1 100644 --- a/sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts +++ b/sdc-workflow-designer-ui/src/app/services/data-access/mockdata.ts @@ -1,2 +1,2 @@ -export const workflowFJH = {"id":"fjh","name":"fjh","nodes":[{"id":"node0","name":"startEvent","type":"startEvent","position":{"top":31,"left":31,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node0","targetRef":"node23"}],"parameters":[{"name":"vlCount","value":"","valueSource":"String","type":"String"},{"name":"vnfCount","value":"","valueSource":"String","type":"String"},{"name":"sfcCount","value":"","valueSource":"String","type":"String"},{"name":"object_context","value":"","valueSource":"String","type":"String"},{"name":"nsInstanceId","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForNs","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForVnf","value":"","valueSource":"String","type":"String"},{"name":"jobId","value":"","valueSource":"String","type":"String"},{"name":"sdnControllerId","value":"","valueSource":"String","type":"String"},{"name":"templateid","value":"","valueSource":"String","type":"String"},{"name":"instanceid","value":"","valueSource":"String","type":"String"},{"name":"sdnolcmurl","value":"","valueSource":"String","type":"String"},{"name":"statusurl","value":"","valueSource":"String","type":"String"}]},{"id":"node1","name":"endEvent","type":"endEvent","position":{"top":668,"left":955,"width":200,"height":100},"sequenceFlows":[]},{"id":"node2","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":120,"left":169,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node2","targetRef":"node3","condition":"${ vl_index <= vlCount and vl_status='active' }","name":"未完成"},{"sourceRef":"node2","targetRef":"node4","condition":"!( vl_index <= vlCount and vl_status='active' )","name":"创建完成"}]},{"id":"node3","name":"createVL","type":"restTask","position":{"top":213,"left":142,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node3","targetRef":"node11"}],"produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"body","valueSource":"String","type":"String","position":"body","schema":{"$ref":"#/definitions/VlPostRequest"}}],"responses":[{"description":"","schema":{"$ref":"#/definitions/VlPostResponse"}}],"serviceName":"nslcm","serviceVersion":"v1","url":"/ns/vls","method":"post"},{"id":"node4","name":"restTask","type":"restTask","position":{"top":115,"left":358,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node4","targetRef":"node5"}],"produces":[],"consumes":[],"parameters":[],"responses":[],"serviceName":"nslcm","serviceVersion":"v1","url":"","method":""},{"id":"node5","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":212,"left":383,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node5","targetRef":"node6","condition":"未完成"},{"sourceRef":"node5","targetRef":"node12","condition":"创建完成"}]},{"id":"node6","name":"createVNF","type":"restTask","position":{"top":306,"left":352,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node6","targetRef":"node7"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node7","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":558,"left":443,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node7","targetRef":"node8"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node8","name":"query_vnf nslcm","type":"restTask","position":{"top":639,"left":216,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node8","targetRef":"node9"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node9","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":539,"left":264,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node9","targetRef":"node7","condition":"未完成"},{"sourceRef":"node9","targetRef":"node10","condition":"已完成"}]},{"id":"node10","name":"scriptTask","type":"scriptTask","position":{"top":303,"left":239,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node10","targetRef":"node5"}]},{"id":"node11","name":"scriptTask","type":"scriptTask","position":{"top":207,"left":34,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node11","targetRef":"node2"}]},{"id":"node12","name":"restTask","type":"restTask","position":{"top":205,"left":732,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node12","targetRef":"node13"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node13","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":287,"left":757,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node13","targetRef":"node14","condition":"未结束"},{"sourceRef":"node13","targetRef":"node18","condition":"已结束"}]},{"id":"node14","name":"createSfc","type":"restTask","position":{"top":440,"left":726,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node14","targetRef":"node15"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node15","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":551,"left":754,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node15","targetRef":"node16"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node16","name":"restTask","type":"restTask","position":{"top":642,"left":589,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node16","targetRef":"node17"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node17","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":551,"left":614,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node17","targetRef":"node15","condition":"未结束"},{"sourceRef":"node17","targetRef":"node19","condition":"已结束"}]},{"id":"node18","name":"restTask","type":"restTask","position":{"top":282,"left":927,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node18","targetRef":"node20"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node19","name":"scriptTask","type":"scriptTask","position":{"top":275,"left":588,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node19","targetRef":"node13"}]},{"id":"node20","name":"Assign_all_status","type":"scriptTask","position":{"top":380,"left":928,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node20","targetRef":"node21"}]},{"id":"node21","name":"post_do","type":"restTask","position":{"top":497,"left":929,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node21","targetRef":"node22"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node22","name":"jobstatus","type":"restTask","position":{"top":586,"left":927,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node22","targetRef":"node1"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node23","name":"scriptTask","type":"scriptTask","position":{"top":16,"left":143,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node23","targetRef":"node2"}],"scriptFormate":"javascript","script":"execution.setVariable(\"vl_index\", 1);\nexecution.setVariable(\"vl_status\", \"active\");"}],"configs":{"microservices":[{"name":"nslcm","version":"v1","swaggerJson":"{\"info\":{\"version\":\"1.0.0\",\"contact\":{\"url\":\"https://gerrit.onap.org/r/#/admin/projects/vfc/nfvo/lcm\",\"name\":\"ONAP VFC team\",\"email\":\"onap-discuss@lists.onap.org\"},\"description\":\"VFC Network Service Lifecycle Management Rest API.\",\"title\":\"ONAP VFC Network Service Lifecycle Management API\"},\"paths\":{\"/ns/sfcs/{sfcInstId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteResponse\"}},\"404\":{\"description\":\"the sfc instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"sfcInstId\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"delete sfc\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_sfc\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/SfcInfo\"}},\"404\":{\"description\":\"the sfc instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"sfc instance id\",\"required\":true,\"type\":\"string\",\"name\":\"sfcInstId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"query the specified sfc info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_sfc\"}},\"/ns/{nsInstanceId}/postdeal\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NSInstPostDetailRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"postdeal\"],\"summary\":\"ns postdeal\",\"consumes\":[\"application/json\"],\"operationId\":\"ns_postdeal\"}},\"/ns/vnfs\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/VnfPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/VnfPostRequest\"},\"description\":\"instantiate request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"vnf create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_vnf\"}},\"/ns/{ns_instance_id}/heal\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"},{\"schema\":{\"$ref\":\"#/definitions/NsHealRequest\"},\"description\":\"healVnfData\",\"required\":true,\"name\":\"healVnfData\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns heal\",\"summary\":\"ns heal\",\"operationId\":\"ns_heal\"}},\"/jobs/{jobId}\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"jobId\"},{\"schema\":{\"$ref\":\"#/definitions/JobProgressRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"tags\":[\"job\"],\"description\":\"\",\"summary\":\"jobstatus\",\"operationId\":\"post_jobprogress\"},\"get\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobDetailInfo\"}}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"job Id\",\"in\":\"path\",\"name\":\"jobId\"},{\"required\":true,\"type\":\"string\",\"description\":\"job response message id\",\"in\":\"query\",\"name\":\"responseId\"}],\"tags\":[\"job\"],\"description\":\"\",\"summary\":\"jobstatus\",\"operationId\":\"get_jobstatus\"}},\"/ns/vls/{vlId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteVlResponse\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"vlId\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"delete vl\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_vl\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/VlInfo\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"vl instance id\",\"required\":true,\"type\":\"string\",\"name\":\"vlId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"query the specified vl info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_vl\"}},\"/ns/vls\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/VlPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/VlPostRequest\"},\"description\":\"instantiate request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"vl create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_vl\"}},\"/ns/sfcs\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/SfcPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/SfcPostRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"sfc create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_sfc\"}},\"/ns/{ns_instance_id}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"The NS instance resource and the associated NS identifier were deleted successfully.\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"}],\"tags\":[\"ns\"],\"description\":\"ns delete\",\"summary\":\"ns delete\",\"operationId\":\"ns_delete\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsInstanceInfo\"}}},\"parameters\":[],\"tags\":[\"ns\"],\"description\":\"ns get\",\"summary\":\"ns get\",\"operationId\":\"ns_instance_get\"}},\"/ns/vnfs/{vnfInstId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteResponse\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"vnfInstId\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"delete vnf\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_vnf\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/VnfInfo\"}},\"404\":{\"description\":\"the vnf instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"vnf instance id\",\"required\":true,\"type\":\"string\",\"name\":\"vnfInstId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"query the specified vnf info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_vnf\"}},\"/ns\":{\"post\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsCreateResponse\"}}},\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/NsCreateRequest\"},\"description\":\"NS Instance Create Request\",\"required\":true,\"name\":\"NSCreateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns create\",\"summary\":\"ns create\",\"operationId\":\"ns_create\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsInstancesInfo\"}}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"job response message id\",\"in\":\"query\",\"name\":\"csarId\"}],\"tags\":[\"ns\"],\"description\":\"ns get\",\"summary\":\"ns get\",\"operationId\":\"ns_instantces_get\"}},\"/ns/{ns_instance_id}/terminate\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"},{\"schema\":{\"$ref\":\"#/definitions/NsTerminateRequest\"},\"description\":\"NsTerminateRequest\",\"required\":true,\"name\":\"NsTerminateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns terminate\",\"summary\":\"ns terminate\",\"operationId\":\"ns_terminate\"}},\"/ns/{nsInstanceId}/scale\":{\"post\":{\"responses\":{\"200\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"201\":{\"description\":\"Invalid Request\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NsScaleRequest\"},\"description\":\"Scale NS Request Body\",\"required\":true,\"name\":\"ScaleNSRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns scale\",\"summary\":\"ns scale\",\"operationId\":\"ns_scale\"}},\"/mandb/{modelName}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"The tables were deleted successfully.\"}},\"description\":\"ns table delete\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"model Name.\",\"in\":\"path\",\"name\":\"modelName\"}],\"produces\":[\"application/json\"],\"tags\":[\"db\"],\"summary\":\"ns table delete\",\"consumes\":[\"application/json\"],\"operationId\":\"ns_table_delete\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/TableInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"query ns table info\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"model Name.\",\"in\":\"path\",\"name\":\"modelName\"}],\"produces\":[\"application/json\"],\"tags\":[\"db\"],\"summary\":\"query ns table info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_ns_table\"}},\"/ns/{nsInstanceId}/Instantiate\":{\"post\":{\"responses\":{\"200\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"201\":{\"description\":\"Invalid Request\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NsInstantiateRequest\"},\"description\":\"NS Instantiate Request Body\",\"required\":true,\"name\":\"NSInstantiateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns Instantiate\",\"summary\":\"ns Instantiate\",\"operationId\":\"ns_Instantiate\"}}},\"schemes\":[\"http\",\"https\"],\"produces\":[\"application/json\"],\"basePath\":\"/api/nslcm/v1\",\"definitions\":{\"NsInstanceInfo\":{\"type\":\"object\",\"properties\":{\"nsState\":{\"type\":\"string\"},\"vnfInfo\":{\"items\":{\"$ref\":\"#/definitions/vnfInfo\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"nsdId\":{\"type\":\"string\"},\"vlInfo\":{\"items\":{\"$ref\":\"#/definitions/vlInfo\"},\"type\":\"array\"},\"nsName\":{\"type\":\"string\"},\"vnffgInfo\":{\"items\":{\"$ref\":\"#/definitions/vnffgInfo\"},\"type\":\"array\"},\"description\":{\"type\":\"string\"}}},\"JobDetailInfo\":{\"type\":\"object\",\"properties\":{\"responseDescriptor\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"},\"responseHistoryList\":{\"items\":{\"$ref\":\"#/definitions/jobResponseInfo\"},\"type\":\"array\"},\"responseId\":{\"type\":\"string\"},\"errorCode\":{\"type\":\"string\"},\"progress\":{\"type\":\"string\"},\"statusDescription\":{\"type\":\"string\"}}},\"jobId\":{\"type\":\"string\"}}},\"VnfInfo\":{\"type\":\"object\",\"properties\":{\"vnfInstId\":{\"type\":\"string\"},\"vnfName\":{\"type\":\"string\"},\"vnfStatus\":{\"type\":\"string\"}}},\"DeleteResponse\":{\"type\":\"object\",\"properties\":{\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"NsHealRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceId\":{\"type\":\"string\"},\"cause\":{\"type\":\"string\"},\"additionalParams\":{\"type\":\"object\",\"properties\":{\"action\":{\"type\":\"string\"},\"actionvminfo\":{\"type\":\"object\",\"properties\":{\"vmname\":{\"type\":\"string\"},\"vmid\":{\"type\":\"string\"}}}}}}},\"NsScaleRequest\":{\"type\":\"object\",\"properties\":{\"scaleNsByStepsData\":{\"$ref\":\"#/definitions/NsScaleByStepsData\"},\"scaleType\":{\"type\":\"string\"}}},\"jobResponseInfo\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"},\"progress\":{\"type\":\"string\"},\"responseId\":{\"type\":\"string\"},\"statusDescription\":{\"type\":\"string\"},\"errorCode\":{\"type\":\"string\"}}},\"NSInstPostDetailRequest\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"}}},\"VlInfo\":{\"type\":\"object\",\"properties\":{\"vlId\":{\"type\":\"string\"},\"vlStatus\":{\"type\":\"string\"},\"vlName\":{\"type\":\"string\"}}},\"VnfPostResponse\":{\"type\":\"object\",\"properties\":{\"vnfInstId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"}}},\"NsCreateRequest\":{\"type\":\"object\",\"properties\":{\"nsName\":{\"type\":\"string\"},\"csarId\":{\"type\":\"string\",\"description\":\"the NS package ID\"},\"description\":{\"type\":\"string\"}}},\"VlPostResponse\":{\"type\":\"object\",\"properties\":{\"vlId\":{\"type\":\"string\"},\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"SfcPostRequest\":{\"type\":\"object\",\"properties\":{\"sdnControllerId\":{\"type\":\"string\"},\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"fpindex\":{\"type\":\"string\"}}},\"NsTerminateRequest\":{\"type\":\"object\",\"properties\":{\"gracefulTerminationTimeout\":{\"type\":\"string\"},\"terminationType\":{\"type\":\"string\"}}},\"JobProgressRequest\":{\"type\":\"object\",\"properties\":{\"progress\":{\"type\":\"string\"},\"errcode\":{\"type\":\"string\"},\"desc\":{\"type\":\"string\"}}},\"SfcInfo\":{\"type\":\"object\",\"properties\":{\"sfcName\":{\"type\":\"string\"},\"sfcInstId\":{\"type\":\"string\"},\"sfcStatus\":{\"type\":\"string\"}}},\"vnfInfo\":{\"type\":\"object\",\"properties\":{\"vnfInstanceId\":{\"type\":\"string\"},\"vnfdId\":{\"type\":\"string\"},\"vnfInstanceName\":{\"type\":\"string\"}}},\"LocationConstraint\":{\"type\":\"object\",\"properties\":{\"locationConstraints\":{\"type\":\"object\",\"properties\":{\"vimid\":{\"type\":\"string\"}}},\"vnfProfileId\":{\"type\":\"string\"}}},\"NsCreateResponse\":{\"type\":\"object\",\"properties\":{\"nsInstanceId\":{\"type\":\"string\"}}},\"VlPostRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"flavourId\":{\"type\":\"string\"},\"pnfInfo\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"extNSVirtualLink\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nestedNsInstanceId\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"jobId\":{\"type\":\"string\"},\"locationConstraints\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"vlIndex\":{\"type\":\"string\"}}},\"VnfPostRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"vnfIndex\":{\"type\":\"string\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"flavourId\":{\"type\":\"string\"},\"pnfInfo\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"extNSVirtualLink\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nestedNsInstanceId\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"jobId\":{\"type\":\"string\"},\"locationConstraints\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"}}},\"DeleteVlResponse\":{\"type\":\"object\",\"properties\":{\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"vlInfo\":{\"type\":\"object\",\"properties\":{\"vldId\":{\"type\":\"string\"},\"vlInstanceName\":{\"type\":\"string\"},\"vlInstanceId\":{\"type\":\"string\"},\"relatedCpInstanceId\":{\"items\":{\"$ref\":\"#/definitions/cpInfo\"},\"type\":\"array\"}}},\"cpInfo\":{\"type\":\"object\",\"properties\":{\"cpInstanceId\":{\"type\":\"string\"},\"cpdId\":{\"type\":\"string\"},\"cpInstanceName\":{\"type\":\"string\"}}},\"SfcPostResponse\":{\"type\":\"object\",\"properties\":{\"sfcInstId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"}}},\"NsInstantiateRequest\":{\"type\":\"object\",\"properties\":{\"additionalParamForNs\":{\"type\":\"string\"},\"LocationConstraints\":{\"items\":{\"$ref\":\"#/definitions/LocationConstraint\"},\"type\":\"array\"}}},\"JobInfo\":{\"type\":\"object\",\"properties\":{\"jobId\":{\"type\":\"string\"}}},\"NsInstancesInfo\":{\"items\":{\"$ref\":\"#/definitions/NsInstanceInfo\"},\"type\":\"array\"},\"NsScaleByStepsData\":{\"type\":\"object\",\"properties\":{\"numberOfSteps\":{\"type\":\"integer\"},\"scalingDirection\":{\"type\":\"string\"},\"aspectId\":{\"type\":\"string\"}}},\"vnffgInfo\":{\"type\":\"object\",\"properties\":{\"cpId\":{\"type\":\"string\"},\"virtualLinkId\":{\"type\":\"string\"},\"vnfId\":{\"type\":\"string\"},\"pnfId\":{\"type\":\"string\"},\"nfp\":{\"type\":\"string\"},\"vnffgInstanceId\":{\"type\":\"string\"}}},\"TableInfo\":{\"type\":\"object\",\"properties\":{\"count\":{\"type\":\"string\"}}}},\"swagger\":\"2.0\",\"consumes\":[\"application/json\"]}","definition":""}]}};
+export const workflowFJH = {"id":"fjh","name":"fjh","nodes":[{"id":"node0","name":"startEvent","type":"startEvent","position":{"top":31,"left":31,"width":200,"height":100},"connection":[{"sourceRef":"node0","targetRef":"node23"}],"parameters":[{"name":"vlCount","value":"","valueSource":"String","type":"String"},{"name":"vnfCount","value":"","valueSource":"String","type":"String"},{"name":"sfcCount","value":"","valueSource":"String","type":"String"},{"name":"object_context","value":"","valueSource":"String","type":"String"},{"name":"nsInstanceId","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForNs","value":"","valueSource":"String","type":"String"},{"name":"object_additionalParamForVnf","value":"","valueSource":"String","type":"String"},{"name":"jobId","value":"","valueSource":"String","type":"String"},{"name":"sdnControllerId","value":"","valueSource":"String","type":"String"},{"name":"templateid","value":"","valueSource":"String","type":"String"},{"name":"instanceid","value":"","valueSource":"String","type":"String"},{"name":"sdnolcmurl","value":"","valueSource":"String","type":"String"},{"name":"statusurl","value":"","valueSource":"String","type":"String"}]},{"id":"node1","name":"endEvent","type":"endEvent","position":{"top":668,"left":955,"width":200,"height":100},"connection":[]},{"id":"node2","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":120,"left":169,"width":200,"height":100},"connection":[{"sourceRef":"node2","targetRef":"node3","condition":"${ vl_index <= vlCount and vl_status='active' }","name":"未完成"},{"sourceRef":"node2","targetRef":"node4","condition":"!( vl_index <= vlCount and vl_status='active' )","name":"创建完成"}]},{"id":"node3","name":"createVL","type":"restTask","position":{"top":213,"left":142,"width":200,"height":100},"connection":[{"sourceRef":"node3","targetRef":"node11"}],"produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"body","valueSource":"String","type":"String","position":"body","schema":{"$ref":"#/definitions/VlPostRequest"}}],"responses":[{"description":"","schema":{"$ref":"#/definitions/VlPostResponse"}}],"restConfigId":"nslcm","path":"/ns/vls","method":"post"},{"id":"node4","name":"restTask","type":"restTask","position":{"top":115,"left":358,"width":200,"height":100},"connection":[{"sourceRef":"node4","targetRef":"node5"}],"produces":[],"consumes":[],"parameters":[],"responses":[],"restConfigId":"nslcm","path":"","method":""},{"id":"node5","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":212,"left":383,"width":200,"height":100},"connection":[{"sourceRef":"node5","targetRef":"node6","condition":"未完成"},{"sourceRef":"node5","targetRef":"node12","condition":"创建完成"}]},{"id":"node6","name":"createVNF","type":"restTask","position":{"top":306,"left":352,"width":200,"height":100},"connection":[{"sourceRef":"node6","targetRef":"node7"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node7","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":558,"left":443,"width":200,"height":100},"connection":[{"sourceRef":"node7","targetRef":"node8"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node8","name":"query_vnf nslcm","type":"restTask","position":{"top":639,"left":216,"width":200,"height":100},"connection":[{"sourceRef":"node8","targetRef":"node9"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node9","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":539,"left":264,"width":200,"height":100},"connection":[{"sourceRef":"node9","targetRef":"node7","condition":"未完成"},{"sourceRef":"node9","targetRef":"node10","condition":"已完成"}]},{"id":"node10","name":"scriptTask","type":"scriptTask","position":{"top":303,"left":239,"width":200,"height":100},"connection":[{"sourceRef":"node10","targetRef":"node5"}]},{"id":"node11","name":"scriptTask","type":"scriptTask","position":{"top":207,"left":34,"width":200,"height":100},"connection":[{"sourceRef":"node11","targetRef":"node2"}]},{"id":"node12","name":"restTask","type":"restTask","position":{"top":205,"left":732,"width":200,"height":100},"connection":[{"sourceRef":"node12","targetRef":"node13"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node13","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":287,"left":757,"width":200,"height":100},"connection":[{"sourceRef":"node13","targetRef":"node14","condition":"未结束"},{"sourceRef":"node13","targetRef":"node18","condition":"已结束"}]},{"id":"node14","name":"createSfc","type":"restTask","position":{"top":440,"left":726,"width":200,"height":100},"connection":[{"sourceRef":"node14","targetRef":"node15"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node15","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":551,"left":754,"width":200,"height":100},"connection":[{"sourceRef":"node15","targetRef":"node16"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node16","name":"restTask","type":"restTask","position":{"top":642,"left":589,"width":200,"height":100},"connection":[{"sourceRef":"node16","targetRef":"node17"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node17","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":551,"left":614,"width":200,"height":100},"connection":[{"sourceRef":"node17","targetRef":"node15","condition":"未结束"},{"sourceRef":"node17","targetRef":"node19","condition":"已结束"}]},{"id":"node18","name":"restTask","type":"restTask","position":{"top":282,"left":927,"width":200,"height":100},"connection":[{"sourceRef":"node18","targetRef":"node20"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node19","name":"scriptTask","type":"scriptTask","position":{"top":275,"left":588,"width":200,"height":100},"connection":[{"sourceRef":"node19","targetRef":"node13"}]},{"id":"node20","name":"Assign_all_status","type":"scriptTask","position":{"top":380,"left":928,"width":200,"height":100},"connection":[{"sourceRef":"node20","targetRef":"node21"}]},{"id":"node21","name":"post_do","type":"restTask","position":{"top":497,"left":929,"width":200,"height":100},"connection":[{"sourceRef":"node21","targetRef":"node22"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node22","name":"jobstatus","type":"restTask","position":{"top":586,"left":927,"width":200,"height":100},"connection":[{"sourceRef":"node22","targetRef":"node1"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node23","name":"scriptTask","type":"scriptTask","position":{"top":16,"left":143,"width":200,"height":100},"connection":[{"sourceRef":"node23","targetRef":"node2"}],"scriptFormate":"javascript","script":"execution.setVariable(\"vl_index\", 1);\nexecution.setVariable(\"vl_status\", \"active\");"}],"configs":{"microservices":[{"name":"nslcm","version":"v1","swaggerJson":"{\"info\":{\"version\":\"1.0.0\",\"contact\":{\"url\":\"https://gerrit.onap.org/r/#/admin/projects/vfc/nfvo/lcm\",\"name\":\"ONAP VFC team\",\"email\":\"onap-discuss@lists.onap.org\"},\"description\":\"VFC Network Service Lifecycle Management Rest API.\",\"title\":\"ONAP VFC Network Service Lifecycle Management API\"},\"paths\":{\"/ns/sfcs/{sfcInstId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteResponse\"}},\"404\":{\"description\":\"the sfc instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"sfcInstId\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"delete sfc\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_sfc\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/SfcInfo\"}},\"404\":{\"description\":\"the sfc instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"sfc instance id\",\"required\":true,\"type\":\"string\",\"name\":\"sfcInstId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"query the specified sfc info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_sfc\"}},\"/ns/{nsInstanceId}/postdeal\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NSInstPostDetailRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"postdeal\"],\"summary\":\"ns postdeal\",\"consumes\":[\"application/json\"],\"operationId\":\"ns_postdeal\"}},\"/ns/vnfs\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/VnfPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/VnfPostRequest\"},\"description\":\"instantiate request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"vnf create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_vnf\"}},\"/ns/{ns_instance_id}/heal\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"},{\"schema\":{\"$ref\":\"#/definitions/NsHealRequest\"},\"description\":\"healVnfData\",\"required\":true,\"name\":\"healVnfData\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns heal\",\"summary\":\"ns heal\",\"operationId\":\"ns_heal\"}},\"/jobs/{jobId}\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"jobId\"},{\"schema\":{\"$ref\":\"#/definitions/JobProgressRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"tags\":[\"job\"],\"description\":\"\",\"summary\":\"jobstatus\",\"operationId\":\"post_jobprogress\"},\"get\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobDetailInfo\"}}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"job Id\",\"in\":\"path\",\"name\":\"jobId\"},{\"required\":true,\"type\":\"string\",\"description\":\"job response message id\",\"in\":\"query\",\"name\":\"responseId\"}],\"tags\":[\"job\"],\"description\":\"\",\"summary\":\"jobstatus\",\"operationId\":\"get_jobstatus\"}},\"/ns/vls/{vlId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteVlResponse\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"vlId\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"delete vl\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_vl\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/VlInfo\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"vl instance id\",\"required\":true,\"type\":\"string\",\"name\":\"vlId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"query the specified vl info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_vl\"}},\"/ns/vls\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/VlPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/VlPostRequest\"},\"description\":\"instantiate request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"vl\"],\"summary\":\"vl create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_vl\"}},\"/ns/sfcs\":{\"post\":{\"responses\":{\"201\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/SfcPostResponse\"}}},\"description\":\"\",\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/SfcPostRequest\"},\"description\":\"request param\",\"required\":true,\"name\":\"body\",\"in\":\"body\"}],\"produces\":[\"application/json\"],\"tags\":[\"sfc\"],\"summary\":\"sfc create\",\"consumes\":[\"application/json\"],\"operationId\":\"create_sfc\"}},\"/ns/{ns_instance_id}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"The NS instance resource and the associated NS identifier were deleted successfully.\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"}],\"tags\":[\"ns\"],\"description\":\"ns delete\",\"summary\":\"ns delete\",\"operationId\":\"ns_delete\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsInstanceInfo\"}}},\"parameters\":[],\"tags\":[\"ns\"],\"description\":\"ns get\",\"summary\":\"ns get\",\"operationId\":\"ns_instance_get\"}},\"/ns/vnfs/{vnfInstId}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/DeleteResponse\"}},\"404\":{\"description\":\"the vl instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"vnfInstId\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"delete vnf\",\"consumes\":[\"application/json\"],\"operationId\":\"delete_vnf\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/VnfInfo\"}},\"404\":{\"description\":\"the vnf instance id is wrong\"},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"\",\"parameters\":[{\"description\":\"vnf instance id\",\"required\":true,\"type\":\"string\",\"name\":\"vnfInstId\",\"in\":\"path\"}],\"produces\":[\"application/json\"],\"tags\":[\"vnf\"],\"summary\":\"query the specified vnf info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_vnf\"}},\"/ns\":{\"post\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsCreateResponse\"}}},\"parameters\":[{\"schema\":{\"$ref\":\"#/definitions/NsCreateRequest\"},\"description\":\"NS Instance Create Request\",\"required\":true,\"name\":\"NSCreateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns create\",\"summary\":\"ns create\",\"operationId\":\"ns_create\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/NsInstancesInfo\"}}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"job response message id\",\"in\":\"query\",\"name\":\"csarId\"}],\"tags\":[\"ns\"],\"description\":\"ns get\",\"summary\":\"ns get\",\"operationId\":\"ns_instantces_get\"}},\"/ns/{ns_instance_id}/terminate\":{\"post\":{\"responses\":{\"202\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"Identifier of the NS instance.\",\"in\":\"path\",\"name\":\"ns_instance_id\"},{\"schema\":{\"$ref\":\"#/definitions/NsTerminateRequest\"},\"description\":\"NsTerminateRequest\",\"required\":true,\"name\":\"NsTerminateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns terminate\",\"summary\":\"ns terminate\",\"operationId\":\"ns_terminate\"}},\"/ns/{nsInstanceId}/scale\":{\"post\":{\"responses\":{\"200\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"201\":{\"description\":\"Invalid Request\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NsScaleRequest\"},\"description\":\"Scale NS Request Body\",\"required\":true,\"name\":\"ScaleNSRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns scale\",\"summary\":\"ns scale\",\"operationId\":\"ns_scale\"}},\"/mandb/{modelName}\":{\"delete\":{\"responses\":{\"204\":{\"description\":\"The tables were deleted successfully.\"}},\"description\":\"ns table delete\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"model Name.\",\"in\":\"path\",\"name\":\"modelName\"}],\"produces\":[\"application/json\"],\"tags\":[\"db\"],\"summary\":\"ns table delete\",\"consumes\":[\"application/json\"],\"operationId\":\"ns_table_delete\"},\"get\":{\"responses\":{\"200\":{\"description\":\"successful operation\",\"schema\":{\"$ref\":\"#/definitions/TableInfo\"}},\"500\":{\"description\":\"the url is invalid\"}},\"description\":\"query ns table info\",\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"model Name.\",\"in\":\"path\",\"name\":\"modelName\"}],\"produces\":[\"application/json\"],\"tags\":[\"db\"],\"summary\":\"query ns table info\",\"consumes\":[\"application/json\"],\"operationId\":\"query_ns_table\"}},\"/ns/{nsInstanceId}/Instantiate\":{\"post\":{\"responses\":{\"200\":{\"description\":\"\",\"schema\":{\"$ref\":\"#/definitions/JobInfo\"}},\"201\":{\"description\":\"Invalid Request\"}},\"parameters\":[{\"required\":true,\"type\":\"string\",\"description\":\"\",\"in\":\"path\",\"name\":\"nsInstanceId\"},{\"schema\":{\"$ref\":\"#/definitions/NsInstantiateRequest\"},\"description\":\"NS Instantiate Request Body\",\"required\":true,\"name\":\"NSInstantiateRequest\",\"in\":\"body\"}],\"tags\":[\"ns\"],\"description\":\"ns Instantiate\",\"summary\":\"ns Instantiate\",\"operationId\":\"ns_Instantiate\"}}},\"schemes\":[\"http\",\"https\"],\"produces\":[\"application/json\"],\"basePath\":\"/api/nslcm/v1\",\"definitions\":{\"NsInstanceInfo\":{\"type\":\"object\",\"properties\":{\"nsState\":{\"type\":\"string\"},\"vnfInfo\":{\"items\":{\"$ref\":\"#/definitions/vnfInfo\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"nsdId\":{\"type\":\"string\"},\"vlInfo\":{\"items\":{\"$ref\":\"#/definitions/vlInfo\"},\"type\":\"array\"},\"nsName\":{\"type\":\"string\"},\"vnffgInfo\":{\"items\":{\"$ref\":\"#/definitions/vnffgInfo\"},\"type\":\"array\"},\"description\":{\"type\":\"string\"}}},\"JobDetailInfo\":{\"type\":\"object\",\"properties\":{\"responseDescriptor\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"},\"responseHistoryList\":{\"items\":{\"$ref\":\"#/definitions/jobResponseInfo\"},\"type\":\"array\"},\"responseId\":{\"type\":\"string\"},\"errorCode\":{\"type\":\"string\"},\"progress\":{\"type\":\"string\"},\"statusDescription\":{\"type\":\"string\"}}},\"jobId\":{\"type\":\"string\"}}},\"VnfInfo\":{\"type\":\"object\",\"properties\":{\"vnfInstId\":{\"type\":\"string\"},\"vnfName\":{\"type\":\"string\"},\"vnfStatus\":{\"type\":\"string\"}}},\"DeleteResponse\":{\"type\":\"object\",\"properties\":{\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"NsHealRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceId\":{\"type\":\"string\"},\"cause\":{\"type\":\"string\"},\"additionalParams\":{\"type\":\"object\",\"properties\":{\"action\":{\"type\":\"string\"},\"actionvminfo\":{\"type\":\"object\",\"properties\":{\"vmname\":{\"type\":\"string\"},\"vmid\":{\"type\":\"string\"}}}}}}},\"NsScaleRequest\":{\"type\":\"object\",\"properties\":{\"scaleNsByStepsData\":{\"$ref\":\"#/definitions/NsScaleByStepsData\"},\"scaleType\":{\"type\":\"string\"}}},\"jobResponseInfo\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"},\"progress\":{\"type\":\"string\"},\"responseId\":{\"type\":\"string\"},\"statusDescription\":{\"type\":\"string\"},\"errorCode\":{\"type\":\"string\"}}},\"NSInstPostDetailRequest\":{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"}}},\"VlInfo\":{\"type\":\"object\",\"properties\":{\"vlId\":{\"type\":\"string\"},\"vlStatus\":{\"type\":\"string\"},\"vlName\":{\"type\":\"string\"}}},\"VnfPostResponse\":{\"type\":\"object\",\"properties\":{\"vnfInstId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"}}},\"NsCreateRequest\":{\"type\":\"object\",\"properties\":{\"nsName\":{\"type\":\"string\"},\"csarId\":{\"type\":\"string\",\"description\":\"the NS package ID\"},\"description\":{\"type\":\"string\"}}},\"VlPostResponse\":{\"type\":\"object\",\"properties\":{\"vlId\":{\"type\":\"string\"},\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"SfcPostRequest\":{\"type\":\"object\",\"properties\":{\"sdnControllerId\":{\"type\":\"string\"},\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"fpindex\":{\"type\":\"string\"}}},\"NsTerminateRequest\":{\"type\":\"object\",\"properties\":{\"gracefulTerminationTimeout\":{\"type\":\"string\"},\"terminationType\":{\"type\":\"string\"}}},\"JobProgressRequest\":{\"type\":\"object\",\"properties\":{\"progress\":{\"type\":\"string\"},\"errcode\":{\"type\":\"string\"},\"desc\":{\"type\":\"string\"}}},\"SfcInfo\":{\"type\":\"object\",\"properties\":{\"sfcName\":{\"type\":\"string\"},\"sfcInstId\":{\"type\":\"string\"},\"sfcStatus\":{\"type\":\"string\"}}},\"vnfInfo\":{\"type\":\"object\",\"properties\":{\"vnfInstanceId\":{\"type\":\"string\"},\"vnfdId\":{\"type\":\"string\"},\"vnfInstanceName\":{\"type\":\"string\"}}},\"LocationConstraint\":{\"type\":\"object\",\"properties\":{\"locationConstraints\":{\"type\":\"object\",\"properties\":{\"vimid\":{\"type\":\"string\"}}},\"vnfProfileId\":{\"type\":\"string\"}}},\"NsCreateResponse\":{\"type\":\"object\",\"properties\":{\"nsInstanceId\":{\"type\":\"string\"}}},\"VlPostRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"flavourId\":{\"type\":\"string\"},\"pnfInfo\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"extNSVirtualLink\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nestedNsInstanceId\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"jobId\":{\"type\":\"string\"},\"locationConstraints\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"vlIndex\":{\"type\":\"string\"}}},\"VnfPostRequest\":{\"type\":\"object\",\"properties\":{\"vnfInstanceData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"vnfIndex\":{\"type\":\"string\"},\"additionalParamForVnf\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nsInstanceId\":{\"type\":\"string\"},\"flavourId\":{\"type\":\"string\"},\"pnfInfo\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"extNSVirtualLink\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"additionalParamForNs\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"context\":{\"type\":\"string\"},\"sapData\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"nestedNsInstanceId\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"},\"jobId\":{\"type\":\"string\"},\"locationConstraints\":{\"items\":{\"type\":\"object\"},\"type\":\"array\"}}},\"DeleteVlResponse\":{\"type\":\"object\",\"properties\":{\"result\":{\"enum\":[0,1],\"type\":\"integer\"},\"detail\":{\"type\":\"string\"}}},\"vlInfo\":{\"type\":\"object\",\"properties\":{\"vldId\":{\"type\":\"string\"},\"vlInstanceName\":{\"type\":\"string\"},\"vlInstanceId\":{\"type\":\"string\"},\"relatedCpInstanceId\":{\"items\":{\"$ref\":\"#/definitions/cpInfo\"},\"type\":\"array\"}}},\"cpInfo\":{\"type\":\"object\",\"properties\":{\"cpInstanceId\":{\"type\":\"string\"},\"cpdId\":{\"type\":\"string\"},\"cpInstanceName\":{\"type\":\"string\"}}},\"SfcPostResponse\":{\"type\":\"object\",\"properties\":{\"sfcInstId\":{\"type\":\"string\"},\"jobId\":{\"type\":\"string\"}}},\"NsInstantiateRequest\":{\"type\":\"object\",\"properties\":{\"additionalParamForNs\":{\"type\":\"string\"},\"LocationConstraints\":{\"items\":{\"$ref\":\"#/definitions/LocationConstraint\"},\"type\":\"array\"}}},\"JobInfo\":{\"type\":\"object\",\"properties\":{\"jobId\":{\"type\":\"string\"}}},\"NsInstancesInfo\":{\"items\":{\"$ref\":\"#/definitions/NsInstanceInfo\"},\"type\":\"array\"},\"NsScaleByStepsData\":{\"type\":\"object\",\"properties\":{\"numberOfSteps\":{\"type\":\"integer\"},\"scalingDirection\":{\"type\":\"string\"},\"aspectId\":{\"type\":\"string\"}}},\"vnffgInfo\":{\"type\":\"object\",\"properties\":{\"cpId\":{\"type\":\"string\"},\"virtualLinkId\":{\"type\":\"string\"},\"vnfId\":{\"type\":\"string\"},\"pnfId\":{\"type\":\"string\"},\"nfp\":{\"type\":\"string\"},\"vnffgInstanceId\":{\"type\":\"string\"}}},\"TableInfo\":{\"type\":\"object\",\"properties\":{\"count\":{\"type\":\"string\"}}}},\"swagger\":\"2.0\",\"consumes\":[\"application/json\"]}","definition":""}]}};
diff --git a/sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts b/sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts index f0013bc5..c6cf60a8 100644 --- a/sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts +++ b/sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts @@ -12,10 +12,13 @@ import { Injectable } from '@angular/core';
import * as jsp from 'jsplumb';
-import { ModelService } from "./model.service";
-import { BroadcastService } from "./broadcast.service";
+
import { Subscription } from 'rxjs/Subscription';
-import { WorkflowNode } from "../model/workflow/workflow-node";
+import { WorkflowNode } from '../model/workflow/workflow-node';
+import { BroadcastService } from './broadcast.service';
+import { ModelService } from './model.service';
+import { SequenceFlow } from '../model/workflow/sequence-flow';
+import { Position } from '../model/workflow/position';
/**
* JsPlumbService
@@ -23,68 +26,120 @@ import { WorkflowNode } from "../model/workflow/workflow-node"; */
@Injectable()
export class JsPlumbService {
- public jsplumbInstance;
+ public jsplumbInstanceMap = new Map<string, any>();
public subscriptionMap = new Map<string, Subscription>();
- constructor(private processService: ModelService, private broadcastService: BroadcastService) {
- this.jsplumbInstance = jsp.jsPlumb.getInstance({
- Container: 'canvas'
+ private padding = 20;
+ private rootClass = 'canvas';
+ private selectNodes: WorkflowNode[] = [];
+
+ constructor(private modelService: ModelService, private broadcastService: BroadcastService) {
+ this.broadcastService.selectedElement$.subscribe(elements => {
+ this.selectNodes = [];
+ if (elements && 0 < elements.length) {
+ for (let index = 0; index < elements.length; index++) {
+ let element = elements[index];
+ if (this.modelService.isNode(element)) {
+ let node = element as WorkflowNode;
+ this.selectNodes.push(node);
+ }
+ }
+ }
});
- this.initJsPlumbInstance();
- this.broadcastService.workflow.subscribe(Workflow => {
- this.jsplumbInstance.reset();
- this.unsubscriptionAll();
- this.initJsPlumbInstance();
- this.buttonDraggable();
- this.buttonDroppable();
+ }
+
+ public connectChildrenNodes(parentNodeId: string) {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(parentNodeId);
+
+ const nodes: WorkflowNode[] = this.modelService.getChildrenNodes(parentNodeId);
+ nodes.forEach(node => this.connect4OneNode(node, jsplumbInstance));
+ }
+
+ public connect4OneNode(node: WorkflowNode, jsplumbInstance: any) {
+ node.connection.forEach(sequenceFlow => {
+ const connection = jsplumbInstance.connect({
+ source: sequenceFlow.sourceRef,
+ target: sequenceFlow.targetRef,
+ });
+ if (sequenceFlow.name) {
+ connection.setLabel(sequenceFlow.name);
+ }
});
}
+ public initJsPlumbInstance(id: string) {
+ if (this.jsplumbInstanceMap.get(id)) {
+ return;
+ }
+ const jsplumbInstance = jsp.jsPlumb.getInstance();
- public initJsPlumbInstance() {
- this.jsplumbInstance.importDefaults({
- Anchor: ['Top', 'RightMiddle', 'LeftMiddle', 'Bottom'],
- Connector: [
- 'Flowchart',
- { cornerRadius: 0, stub: 0, gap: 3 },
- ],
- ConnectionOverlays: [
- [
- 'Arrow',
- { direction: 1, foldback: 1, location: 1, width: 10, length: 10 },
- ],
- ['Label', { label: '', id: 'label', cssClass: 'aLabel' }],
- ],
- Endpoint: 'Blank',
+ jsplumbInstance.importDefaults({
+ Anchor: "Continuous",
+ Endpoint: "Blank",
+ Container: "pallete",
+ ReattachConnections: true,
+ Connector: ['Flowchart', {
+ stub: [0, 0],
+ cornerRadius: 5,
+ alwaysRespectStubs: true
+ }],
PaintStyle: {
- strokeWidth: 4,
- stroke: 'black',
+ stroke: "#7D8695",
+ strokeWidth: 1,
+ radius: 1,
+ outlineStroke: "transform",
+ outlineWidth: 4
},
- HoverPaintStyle: {
- strokeWidth: 4,
- stroke: 'blue',
+ ConnectorStyle: {
+ stroke: "#7D8695",
+ strokeWidth: 1,
+ outlineStroke: "transform",
+ outlineWidth: 4
},
+ ConnectorHoverStyle: {
+ stroke: "#00ABFF",
+ strokeWidth: 2,
+ outlineStroke: "transform",
+ outlineWidth: 4
+ },
+ ConnectionOverlays: [
+ ['Arrow', {
+ location: 1,
+ id: 'arrow',
+ cssClass: 'icon-port',
+ width: 11,
+ length: 12
+ }],
+ ['Label', { label: '', id: 'label' }]
+ ]
});
// add connection to model data while a new connection is build
- this.jsplumbInstance.bind('connection', info => {
- this.processService.addSequenceFlow(info.connection.sourceId, info.connection.targetId);
+ jsplumbInstance.bind('connection', info => {
+ this.modelService.addConnection(info.connection.sourceId, info.connection.targetId);
this.subscribe4Connection(info.connection);
- info.connection.bind('click', connection => {
- const sequenceFlow = this.processService.getSequenceFlow(connection.sourceId, connection.targetId);
- this.broadcastService.broadcast(this.broadcastService.currentSequenceFlow, sequenceFlow);
- this.broadcastService.broadcast(this.broadcastService.currentType, 'SequenceFlow');
+ info.connection.bind('click', (connection, event) => {
+ if ('Label' === connection.type) {
+ return;
+ }
+ event.stopPropagation();
+ const sequenceFlow = this.modelService.getSequenceFlow(connection.sourceId, connection.targetId);
+ this.broadcastService.broadcast(this.broadcastService.showProperty, null);
+ this.broadcastService.broadcast(this.broadcastService.selectedElement, [sequenceFlow]);
});
info.connection.bind('dblclick', connection => {
- const sequenceFlow = this.processService.getSequenceFlow(connection.sourceId, connection.targetId);
- this.broadcastService.broadcast(this.broadcastService.sequenceFlow, sequenceFlow);
- this.broadcastService.broadcast(this.broadcastService.showSequenceFlow, true);
+ if ('Label' === connection.type) {
+ return;
+ }
+ const sequenceFlow = this.modelService.getSequenceFlow(connection.sourceId, connection.targetId);
+ this.broadcastService.broadcast(this.broadcastService.showProperty, sequenceFlow);
});
});
+ this.jsplumbInstanceMap.set(id, jsplumbInstance);
}
private subscribe4Connection(connection: any) {
@@ -94,128 +149,414 @@ export class JsPlumbService { sequenceFlowSubscription.unsubscribe();
}
- sequenceFlowSubscription = this.broadcastService.currentSequenceFlow$.subscribe(currentSequenceFlow => {
- if (currentSequenceFlow.sourceRef === connection.sourceId
- && currentSequenceFlow.targetRef === connection.targetId) {
- connection.setPaintStyle({ stroke: 'red' });
+ let currentThis = this;
+ sequenceFlowSubscription = this.broadcastService.selectedElement$.subscribe(elements => {
+ let selected = false;
+ if (elements && 0 < elements.length) {
+ for (let index = 0; index < elements.length; index++) {
+ let element = elements[index];
+ if (!this.modelService.isNode(element)) {
+ let sequence = element as SequenceFlow;
+ if (sequence.sourceRef === connection.sourceId
+ && sequence.targetRef === connection.targetId) {
+ selected = true;
+ }
+ }
+ }
+ }
+ if (selected) {
+ connection.setPaintStyle({
+ stroke: '#00ABFF',
+ strokeWidth: 1,
+ radius: 1,
+ outlineStroke: "transform",
+ outlineWidth: 4
+ });
} else {
- connection.setPaintStyle({ stroke: 'black' });
+ connection.setPaintStyle({
+ stroke: '#7D8695',
+ strokeWidth: 1,
+ radius: 1,
+ outlineStroke: "transform",
+ outlineWidth: 4
+ });
}
});
-
this.subscriptionMap.set(pre + 'sequenceFlowSubscription', sequenceFlowSubscription);
-
- let typeSubscription = this.subscriptionMap.get(pre + 'typeSubscription');
- if (typeSubscription && !typeSubscription.closed) {
- typeSubscription.unsubscribe();
- }
- typeSubscription = this.broadcastService.currentType$.subscribe(type => {
- if (type === 'WorkflowNode') {
- connection.setPaintStyle({ stroke: 'black' });
- }
- });
- this.subscriptionMap.set(pre + 'typeSubscription', typeSubscription);
}
private unsubscription4Connection(connectionSelection: any) {
connectionSelection.each(connection => {
const pre = connection.sourceId + connection.targetId;
this.subscriptionMap.get(pre + 'sequenceFlowSubscription').unsubscribe();
- this.subscriptionMap.get(pre + 'typeSubscription').unsubscribe();
});
}
- private unsubscriptionAll() {
- this.subscriptionMap.forEach(subscription => subscription.unsubscribe());
+ public deleteConnect(sourceId: string, targetId: string) {
+ const sourceNode = this.modelService.getNodeMap().get(sourceId);
+ const jsplumbInstance = this.jsplumbInstanceMap.get(sourceNode.parentId);
+ const connectionSelection = jsplumbInstance.select({ source: sourceId, target: targetId });
+ this.unsubscription4Connection(connectionSelection);
+ connectionSelection.delete();
+ }
+
+ public setLabel(sourceId: string, targetId: string, label: string) {
+ const sourceNode = this.modelService.getNodeMap().get(sourceId);
+ const jsplumbInstance = this.jsplumbInstanceMap.get(sourceNode.parentId);
+ const connections = jsplumbInstance.select({ source: sourceId, target: targetId });
+ connections.setLabel(label);
}
- public initNode() {
- this.processService.getProcess().forEach(node => {
- this.jsplumbInstance.draggable(node.id, {
- stop: event => {
- node.position.left = event.pos[0];
- node.position.top = event.pos[1];
- },
- });
+ public getParentNodeId(id: string): string {
+ const nodeElement = jsp.jsPlumb.getSelector('#' + id);
+ const parentNode = this.getParentNodeEl(nodeElement[0]);
- this.jsplumbInstance.makeTarget(node.id, {
- detachable: false,
- isTarget: true,
- maxConnections: -1,
- });
+ return parentNode ? parentNode.id : null;
+ }
- this.jsplumbInstance.makeSource(node.id, {
- filter: '.anchor, .anchor *',
- detachable: false,
- isSource: true,
- maxConnections: -1,
- });
+ public initNode(node: WorkflowNode) {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);
+
+ this.jsplumbInstanceMap.get(this.modelService.rootNodeId).draggable(node.id, {
+ scope: 'node',
+ filter: '.ui-resizable-handle',
+ classes: {
+ 'ui-draggable': 'dragging'
+ },
+ // grid: [5, 5],
+ drag: event => {
+ // out of container edge, reset to minimal value.
+ if (0 > event.pos[0]) {
+ event.el.style.left = '0px';
+ }
+ if (0 > event.pos[1]) {
+ event.el.style.top = '0px';
+ }
+
+ if (0 < this.selectNodes.length) {
+ let moveAll = false;
+ this.selectNodes.forEach(element => {
+ if (element.id === event.el.id) {
+ moveAll = true;
+ }
+ });
+ if (moveAll) {
+ this.selectNodes.forEach(selectNode => {
+ if (selectNode.id !== event.el.id) {
+ selectNode.position.left += event.e.movementX;
+ selectNode.position.left = 0 > selectNode.position.left ? 0 : selectNode.position.left;
+ selectNode.position.top += event.e.movementY;
+ selectNode.position.top = 0 > selectNode.position.top ? 0 : selectNode.position.top;
+ }
+ jsplumbInstance.revalidate(jsplumbInstance.getSelector('#' + selectNode.id));
+ });
+ }
+ }
+ },
+ stop: event => {
+ this.selectNodes.forEach(selectNode => {
+ jsplumbInstance.revalidate(jsplumbInstance.getSelector('#' + selectNode.id));
+ });
+ }
+ });
+
+ jsplumbInstance.makeTarget(node.id, {
+ maxConnections: -1,
+ beforeDrop: function (info) {
+ const sourceId = info.sourceId;
+ const targetId = info.targetId;
+ if (sourceId === targetId) {
+ return false;
+ }
+ const sameConnections = this.instance.getConnections({ source: sourceId, target: targetId });
+ if (sameConnections && 0 < sameConnections.length) {
+ return false;
+ }
+ return true;
+ }
+
+ });
+
+ jsplumbInstance.makeSource(node.id, {
+ filter: '.anchor, .anchor *',
+ maxConnections: -1,
});
}
- public connectNodes() {
- const nodes: WorkflowNode[] = this.processService.getProcess();
- nodes.forEach(node => this.connect4OneNode(node));
+ public nodeDroppable(node: WorkflowNode, rank: number) {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);
+
+ const selector = jsplumbInstance.getSelector('#' + node.id);
+ this.jsplumbInstanceMap.get(this.modelService.rootNodeId).droppable(selector, {
+ scope: 'node',
+ rank,
+ tolerance: 'pointer',
+ drop: event => {
+ if (!this.isChildNode(event.drop.el, event.drag.el)) {
+ this.drop(event);
+ }
+ return true;
+ },
+ canDrop: drag => {
+ const nodeMap = this.modelService.getNodeMap();
+ const ancestorNode = nodeMap.get(drag.el.id);
+
+ const isAncestor = this.modelService.isDescendantNode(ancestorNode, node.id);
+ return !isAncestor;
+ },
+ });
}
- public connect4OneNode(node: WorkflowNode) {
- node.sequenceFlows.forEach(sequenceFlow => {
- const connection = this.jsplumbInstance.connect({
- source: sequenceFlow.sourceRef,
- target: sequenceFlow.targetRef,
- });
- if (sequenceFlow.name) {
- connection.setLabel(sequenceFlow.name);
+ private isChildNode(childElement, parentElement) {
+ while (childElement !== parentElement) {
+ childElement = childElement.parentNode;
+ if (childElement.classList.contains('canvas')) {
+ return false;
}
- });
+ }
+
+ return true;
}
- public setLabel(sourceId: string, targetId: string, label: string) {
- const sourceNode = this.processService.getNodeById(sourceId);
- const connections = this.jsplumbInstance.select({ source: sourceId, target: targetId });
- connections.setLabel(label);
+ private drop(event) {
+ const dragEl = event.drag.el;
+ const dropEl = event.drop.el;
+
+ this.resizeParent(dragEl, dropEl);
+
+ const nodeLeft = dragEl.getBoundingClientRect().left;
+ const nodeTop = dragEl.getBoundingClientRect().top;
+ const parentLeft = dropEl.getBoundingClientRect().left;
+ const parentTop = dropEl.getBoundingClientRect().top;
+ const left = nodeLeft - parentLeft + dropEl.scrollLeft;
+ const top = nodeTop - parentTop + dropEl.scrollTop;
+ dragEl.style.top = top + 'px';
+ dragEl.style.left = left + 'px';
+
+ // 12 is title height
+ this.modelService.updatePosition(dragEl.id, left, top, dragEl.getBoundingClientRect().width, dragEl.getBoundingClientRect().height - 12);
+
+ const originalParentNode = this.getParentNodeEl(dragEl);
+ const originalParentNodeId = originalParentNode ? originalParentNode.id : this.modelService.rootNodeId;
+
+ const targetParentNodeId = dropEl.classList.contains('node') ? dropEl.id : this.modelService.rootNodeId;
+ this.changeParent(dragEl.id, originalParentNodeId, targetParentNodeId);
}
- public deleteConnect(sourceId: string, targetId: string) {
- const sourceNode = this.processService.getNodeById(sourceId);
- const connectionSelection = this.jsplumbInstance.select({ source: sourceId, target: targetId });
- this.unsubscription4Connection(connectionSelection);
- connectionSelection.delete();
+ private changeParent(id: string, originalParentNodeId: string, targetParentNodeId: string) {
+ if (originalParentNodeId !== targetParentNodeId) {
+ this.jsplumbInstanceMap.get(originalParentNodeId).removeAllEndpoints(id);
+ this.modelService.changeParent(id, originalParentNodeId, targetParentNodeId);
+ }
}
- public remove(nodeId: string) {
- // unsubscription4Connection
- const connectionsAsSource = this.jsplumbInstance.select({ source: nodeId });
- this.unsubscription4Connection(connectionsAsSource);
- const connectionsAsTarget = this.jsplumbInstance.select({ target: nodeId });
- this.unsubscription4Connection(connectionsAsTarget);
+ private getParentNodeEl(element) {
+ while (!(element.parentNode.classList.contains('node') || element.parentNode.classList.contains('canvas'))) {
+ element = element.parentNode;
+ }
- this.jsplumbInstance.remove(nodeId);
+ if (element.parentNode.classList.contains('canvas')) { // top level node
+ return null;
+ } else {
+ return element.parentNode;
+ }
+ }
+
+ public canvasDroppable() {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);
+ const canvasSelector = jsplumbInstance.getSelector('.canvas');
+ jsplumbInstance.droppable(canvasSelector, {
+ scope: 'node',
+ rank: 0,
+ grid: [5, 5],
+ drop: event => this.drop(event),
+ });
}
public buttonDraggable() {
- const selector = this.jsplumbInstance.getSelector('.toolbar .item');
- this.jsplumbInstance.draggable(selector,
- {
- scope: 'btn',
- clone: true,
- });
+ const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);
+ const selector = jsplumbInstance.getSelector('.item');
+ jsplumbInstance.draggable(selector, {
+ scope: 'btn',
+ clone: true
+ });
}
public buttonDroppable() {
- const selector = this.jsplumbInstance.getSelector('.canvas');
- this.jsplumbInstance.droppable(selector, {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(this.modelService.rootNodeId);
+ const selector = jsplumbInstance.getSelector('.canvas');
+ jsplumbInstance.droppable(selector, {
scope: 'btn',
+ // grid: [5, 5],
drop: event => {
- const el = this.jsplumbInstance.getSelector(event.drag.el);
+ const el = jsplumbInstance.getSelector(event.drag.el);
const type = el.attributes.nodeType.value;
- // Mouse position minus drop canvas start position and minus icon half size
- const left = event.e.clientX - 220 - (event.e.offsetX / 2);
- const top = event.e.clientY - 70 - (event.e.offsetY / 2);
-
- this.processService.addNode(type, type, top, left);
+ // Mouse position minus drop canvas start position plus scroll position.
+ let left = event.e.x - event.drop.pagePosition[0] + event.drop.el.scrollLeft;
+ let top = event.e.y - event.drop.pagePosition[1] + event.drop.el.scrollTop;
+ if (0 > left) {
+ left = 0;
+ }
+ if (0 > top) {
+ top = 0;
+ }
+ const name = event.drag.el.children[1].innerText;
+ this.modelService.addNode(name, type, left, top);
},
});
}
+ public remove(node: WorkflowNode) {
+ const jsplumbInstance = this.jsplumbInstanceMap.get(node.parentId);
+
+ // unsubscription4Connection
+ const connectionsAsSource = jsplumbInstance.select({ source: node.id });
+ this.unsubscription4Connection(connectionsAsSource);
+ const connectionsAsTarget = jsplumbInstance.select({ target: node.id });
+ this.unsubscription4Connection(connectionsAsTarget);
+
+ jsplumbInstance.remove(node.id);
+ }
+
+ public resizeParent(element: any, parentElement: any) {
+ if (parentElement.classList.contains(this.rootClass)) {
+ return;
+ }
+
+ if (!parentElement.classList.contains('node')) {
+ this.resizeParent(element, parentElement.parentNode);
+ return;
+ }
+
+ const leftResized = this.resizeParentLeft(element, parentElement);
+ const rightResized = this.resizeParentRight(element, parentElement);
+ const topResized = this.resizeParentTop(element, parentElement);
+ const bottomResized = this.resizeParentBottom(element, parentElement);
+
+ if (leftResized || rightResized || topResized || bottomResized) {
+ if (parentElement.classList.contains('node')) {
+ const rect = parentElement.getBoundingClientRect();
+ this.modelService.updatePosition(parentElement.id,
+ parentElement.offsetLeft,
+ parentElement.offsetTop,
+ // title height
+ rect.width, rect.height - 12);
+ }
+ this.resizeParent(parentElement, parentElement.parentNode);
+ }
+ }
+
+ private resizeParentLeft(element: any, parentElement: any): boolean {
+ let resized = false;
+
+ const actualLeft = element.getBoundingClientRect().left;
+ const actualParentLeft = parentElement.getBoundingClientRect().left;
+
+ if (actualLeft - this.padding < actualParentLeft) {
+ const width = actualParentLeft - actualLeft + this.padding;
+
+ this.translateElement(parentElement, -width, 0, width, 0);
+ this.translateChildren(parentElement, element, width, 0);
+ resized = true;
+ }
+
+ return resized;
+ }
+
+ private resizeParentRight(element: any, parentElement: any): boolean {
+ let resized = false;
+
+ const actualLeft = element.getBoundingClientRect().left;
+ const actualRight = actualLeft + element.offsetWidth;
+
+ const actualParentLeft = parentElement.getBoundingClientRect().left;
+
+ if ((actualParentLeft + parentElement.offsetWidth) < actualRight + this.padding) {
+ this.setElementWidth(parentElement, actualRight + this.padding - actualParentLeft);
+ resized = true;
+ }
+
+ return resized;
+ }
+
+ private resizeParentBottom(element: any, parentElement: any): boolean {
+ let resized = false;
+
+ const actualTop = element.getBoundingClientRect().top;
+ const actualBottom = actualTop + element.offsetHeight;
+
+ const actualParentTop = parentElement.getBoundingClientRect().top;
+ const actualParentBottom = actualParentTop + parentElement.offsetHeight;
+
+ if (actualParentBottom < actualBottom + this.padding) {
+ this.setElementHeight(parentElement, actualBottom + this.padding - actualParentTop);
+ resized = true;
+ }
+
+ return resized;
+ }
+
+ private resizeParentTop(element: any, parentElement: any): boolean {
+ let resized = false;
+
+ const actualTop = element.getBoundingClientRect().top;
+ const actualParentTop = parentElement.getBoundingClientRect().top;
+
+ if (actualTop - this.padding < actualParentTop) {
+ const height = actualParentTop - actualTop + this.padding;
+
+ this.translateElement(parentElement, 0, -height, 0, height);
+ this.translateChildren(parentElement, element, 0, height);
+ resized = true;
+ }
+
+ return resized;
+ }
+
+ private translateElement(element, left: number, top: number, width: number, height: number) {
+ const offsetLeft = element.offsetLeft + left;
+ element.style.left = offsetLeft + 'px';
+
+ const offsetTop = element.offsetTop + top;
+ element.style.top = offsetTop + 'px';
+
+ const offsetWidth = element.offsetWidth + width;
+ element.style.width = offsetWidth + 'px';
+
+ const offsetHeight = element.offsetHeight + height;
+ element.style.height = offsetHeight + 'px';
+
+ if (element.classList.contains('node')) {
+ const node = this.modelService.getNodeMap().get(element.id);
+ this.jsplumbInstanceMap.get(node.parentId).revalidate(element.id);
+ }
+ }
+
+ private translateChildren(parentElment, excludeElement, left: number, top: number) {
+ const len = parentElment.children.length;
+ for (let i = 0; i < len; i++) {
+ const childElment = parentElment.children[i];
+ if (childElment.localName === 'b4t-node') {
+ this.translateElement(childElment.children[0], left, top, 0, 0);
+ }
+ }
+ }
+
+ private setElementHeight(element, height: number) {
+ element.style.height = height + 'px';
+ }
+
+ private setElementWidth(element, width: number) {
+ element.style.width = width + 'px';
+ }
+
+ private getActualPosition(element, offset: string) {
+ let actualPosition = element[offset];
+ let current = element.offsetParent;
+ while (current !== null) {
+ actualPosition += element[offset];
+ current = current.offsetParent;
+ }
+ return actualPosition;
+ }
}
diff --git a/sdc-workflow-designer-ui/src/app/services/model.service.ts b/sdc-workflow-designer-ui/src/app/services/model.service.ts index 6ce49d04..65d3e490 100644 --- a/sdc-workflow-designer-ui/src/app/services/model.service.ts +++ b/sdc-workflow-designer-ui/src/app/services/model.service.ts @@ -18,12 +18,22 @@ import { NodeType } from "../model/workflow/node-type.enum"; import { StartEvent } from "../model/workflow/start-event";
import { SequenceFlow } from "../model/workflow/sequence-flow";
import { RestTask } from "../model/workflow/rest-task";
+import { ErrorEvent } from "../model/workflow/error-event";
import { PlanTreeviewItem } from "../model/plan-treeview-item";
import { WorkflowConfigService } from "./workflow-config.service";
import { Swagger, SwaggerModelSimple, SwaggerReferenceObject } from "../model/swagger";
import { WorkflowService } from "./workflow.service";
import { IntermediateCatchEvent } from "../model/workflow/intermediate-catch-event";
import { ScriptTask } from "../model/workflow/script-task";
+import { ToscaNodeTask } from '../model/workflow/tosca-node-task';
+import { NodeTemplate } from '../model/topology/node-template';
+import { SubProcess } from '../model/workflow/sub-process';
+import { TimerEventDefinition, TimerEventDefinitionType } from '../model/workflow/timer-event-definition';
+import { Parameter } from '../model/workflow/parameter';
+import { ValueSource } from '../model/value-source.enum';
+import { RestService } from './rest.service';
+import { BroadcastService } from './broadcast.service';
+import { RestConfig } from '../model/rest-config';
/**
* WorkflowService
@@ -31,78 +41,231 @@ import { ScriptTask } from "../model/workflow/script-task"; */
@Injectable()
export class ModelService {
-
- constructor(private workflowService: WorkflowService, private configService: WorkflowConfigService) {
-
+ public rootNodeId = 'root';
+
+ private planModel: PlanModel = new PlanModel();
+
+ constructor(private broadcastService: BroadcastService, private restService: RestService, private workflowService: WorkflowService, private configService: WorkflowConfigService) {
+ this.broadcastService.planModel$.subscribe(plan => {
+ plan.nodes.forEach(node => {
+ switch (node.type) {
+ case NodeType[NodeType.startEvent]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.endEvent]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.restTask]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.errorStartEvent]:
+ case NodeType[NodeType.errorEndEvent]:
+ node.position.width = 26;
+ node.position.height = 26;
+ break;
+ case NodeType[NodeType.toscaNodeManagementTask]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.subProcess]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.intermediateCatchEvent]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.scriptTask]:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ case NodeType[NodeType.exclusiveGateway]:
+ case NodeType[NodeType.parallelGateway]:
+ node.position.width = 26;
+ node.position.height = 26;
+ break;
+ default:
+ node.position.width = 56;
+ node.position.height = 56;
+ break;
+ }
+ });
+ this.planModel = plan;
+ });
+ this.broadcastService.updateModelRestConfig$.subscribe(restConfigs => {
+ this.updateRestConfig(restConfigs);
+ });
}
public getProcess(): WorkflowNode[] {
return this.workflowService.planModel.nodes;
}
- public addNode(name: string, type: string, top: number, left: number): WorkflowNode {
- let node: WorkflowNode;
- switch (type) {
- case NodeType[NodeType.startEvent]:
- node = new StartEvent(this.createId(), name, type, new Position(top, left), []);
- break;
- case NodeType[NodeType.restTask]:
- node = new RestTask(this.createId(), name, type, new Position(top, left), []);
- break;
- case NodeType[NodeType.intermediateCatchEvent]:
- node = new IntermediateCatchEvent(this.createId(), name, type, new Position(top, left), []);
- break;
- case NodeType[NodeType.scriptTask]:
- node = new ScriptTask(this.createId(), name, type, new Position(top, left), []);
- break;
- default:
- node = new WorkflowNode(this.createId(), name, type, new Position(top, left), []);
- break;
+ public getNodes(): WorkflowNode[] {
+ return this.planModel.nodes;
+ }
+
+ public addConnection(sourceId: string, targetId: string) {
+ const node = this.getNodeMap().get(sourceId);
+ if (node) {
+ const index = node.connection.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);
+ if (index === -1) {
+ const sequenceFlow: SequenceFlow = { sourceRef: sourceId, targetRef: targetId };
+ node.connection.push(sequenceFlow);
+ }
}
+ }
- this.getProcess().push(node);
- return node;
+ public deleteConnection(sourceId: string, targetId: string) {
+ const node = this.getNodeMap().get(sourceId);
+ if (node) {
+ const index = node.connection.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);
+ if (index !== -1) {
+ node.connection.splice(index, 1);
+ }
+ }
}
- public deleteNode(nodeId: string): WorkflowNode {
+ public deleteNode(parentId: string, nodeId: string): WorkflowNode {
+ const nodeMap = this.getNodeMap();
+
+ const nodes = this.getChildrenNodes(parentId);
+
// delete related connections
- this.getProcess().forEach(node => this.deleteSequenceFlow(node.id, nodeId));
+ nodes.forEach(node => this.deleteConnection(node.id, nodeId));
// delete current node
- const index = this.getProcess().findIndex(node => node.id === nodeId);
+ const index = nodes.findIndex(node => node.id === nodeId);
if (index !== -1) {
- const node = this.getProcess().splice(index, 1)[0];
- node.sequenceFlows = [];
+ const node = nodes.splice(index, 1)[0];
+ node.connection = [];
return node;
}
- return undefined;
+ return null;
}
- public addSequenceFlow(sourceId: string, targetId: string) {
- const node = this.getNodeById(sourceId);
- if (node) {
- const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);
- if (index === -1) {
- node.sequenceFlows.push(new SequenceFlow(sourceId, targetId));
- }
+ public addChild(parentId: string, child: WorkflowNode) {
+ this.getChildrenNodes(parentId).push(child);
+ }
+
+ public deleteChild(node: SubProcess, id: string): WorkflowNode {
+ const index = node.children.findIndex(child => child.id === id);
+ if (index !== -1) {
+ const deletedNode = node.children.splice(index, 1);
+ return deletedNode[0];
}
+
+ return null;
}
- public deleteSequenceFlow(sourceId: string, targetId: string) {
- const node = this.getNodeById(sourceId);
- if (node) {
- const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);
- if (index !== -1) {
- node.sequenceFlows.splice(index, 1);
+ public updateRestConfig(restConfigs: RestConfig[]): void {
+ this.planModel.configs = { restConfigs: restConfigs };
+ // console.log(this.planModel.configs);
+ }
+
+ public getNodeMap(): Map<string, WorkflowNode> {
+ const map = new Map<string, WorkflowNode>();
+ this.toNodeMap(this.planModel.nodes, map);
+ return map;
+ }
+
+ private toNodeMap(nodes: WorkflowNode[], map: Map<string, WorkflowNode>) {
+ nodes.forEach(node => {
+ if (node.type === 'subProcess') {
+ this.toNodeMap((<SubProcess>node).children, map);
}
+ map.set(node.id, node);
+ });
+ }
+
+ public addNode(name: string, type: string, left: number, top: number) {
+ const id = this.createId();
+ const workflowPos = new Position(left, top);
+ const node = this.createNodeByType(id, name, type, workflowPos);
+ this.planModel.nodes.push(node);
+ }
+
+ private createNodeByType(id: string, name: string, type: string, position: Position): WorkflowNode {
+ const bigPosition = new Position(position.left, position.top, 56, 56);
+ const smallPosition = new Position(position.left, position.top, 26, 26);
+ switch (type) {
+ case NodeType[NodeType.startEvent]:
+ let startEventNode: StartEvent = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], parameters: []
+ };
+ return startEventNode;
+ case NodeType[NodeType.endEvent]:
+ let endEventNode: WorkflowNode = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: []
+ };
+ return endEventNode;
+ case NodeType[NodeType.restTask]:
+ let restTaskNode: RestTask = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], produces: [], consumes: [], parameters: [], responses: []
+ };
+ return restTaskNode;
+ case NodeType[NodeType.errorStartEvent]:
+ case NodeType[NodeType.errorEndEvent]:
+ let errorEventNode: ErrorEvent = {
+ id: id, type: type, name: '', parentId: this.rootNodeId,
+ position: smallPosition, connection: [], parameter: new Parameter('errorRef', '', ValueSource[ValueSource.String])
+ };
+ return errorEventNode;
+ case NodeType[NodeType.toscaNodeManagementTask]:
+ let toscaNodeTask: ToscaNodeTask = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], input: [], output: [], template: new NodeTemplate()
+ };
+ return toscaNodeTask;
+ case NodeType[NodeType.subProcess]:
+ let subProcess: SubProcess = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], children: []
+ };
+ return subProcess;
+ case NodeType[NodeType.intermediateCatchEvent]:
+ let intermediateCatchEvent: IntermediateCatchEvent = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], timerEventDefinition: <TimerEventDefinition>{ type: TimerEventDefinitionType[TimerEventDefinitionType.timeDuration] }
+ };
+ return intermediateCatchEvent;
+ case NodeType[NodeType.scriptTask]:
+ let scriptTask: ScriptTask = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: [], scriptFormat: 'JavaScript'
+ };
+ return scriptTask;
+ case NodeType[NodeType.exclusiveGateway]:
+ case NodeType[NodeType.parallelGateway]:
+ let getway: WorkflowNode = {
+ id: id, type: type, name: '', parentId: this.rootNodeId,
+ position: smallPosition, connection: []
+ };
+ return getway;
+ default:
+ let node: WorkflowNode = {
+ id: id, type: type, name: name, parentId: this.rootNodeId,
+ position: bigPosition, connection: []
+ };
+ return node;
}
}
+ public isNode(object: any): boolean {
+ return undefined !== object.type;
+ }
+
public getSequenceFlow(sourceRef: string, targetRef: string): SequenceFlow {
const node = this.getNodeById(sourceRef);
if (node) {
- const sequenceFlow = node.sequenceFlows.find(tmp => tmp.targetRef === targetRef);
+ const sequenceFlow = node.connection.find(tmp => tmp.targetRef === targetRef);
return sequenceFlow;
} else {
return undefined;
@@ -123,6 +286,9 @@ export class ModelService { case NodeType[NodeType.startEvent]:
params.push(this.loadOutput4StartEvent(<StartEvent>node));
break;
+ case NodeType[NodeType.toscaNodeManagementTask]:
+ params.push(this.loadOutput4ToscaNodeTask(<ToscaNodeTask>node));
+ break;
case NodeType[NodeType.restTask]:
params.push(this.loadOutput4RestTask(<RestTask>node));
break;
@@ -135,54 +301,73 @@ export class ModelService { }
private loadOutput4StartEvent(node: StartEvent): PlanTreeviewItem {
- const startItem = new PlanTreeviewItem(node.name, `[${node.id}]`, []);
+ const startItem = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);
node.parameters.map(param =>
startItem.children.push(new PlanTreeviewItem(param.name, `[${param.name}]`, [])));
return startItem;
}
+ private loadOutput4ToscaNodeTask(node: ToscaNodeTask): PlanTreeviewItem {
+ const item = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);
+ item.children.push(this.createStatusCodeTreeViewItem(node.id));
+ const responseItem = this.createResponseTreeViewItem(node.id);
+ item.children.push(responseItem);
+
+ node.output.map(param =>
+ responseItem.children.push(new PlanTreeviewItem(param.name, `${responseItem.value}.[${param.name}]`, [])));
+ return item;
+ }
+
private loadOutput4RestTask(node: RestTask): PlanTreeviewItem {
- const item = new PlanTreeviewItem(node.name, `[${node.id}]`, []);
+ const item = new PlanTreeviewItem(node.name, `[${node.id}]`, [], false);
item.children.push(this.createStatusCodeTreeViewItem(node.id));
if (node.responses.length !== 0) { // load rest responses
const responseItem = this.createResponseTreeViewItem(node.id);
item.children.push(responseItem);
+ // todo: should list all available response or only the first one?
if (node.responses[0]) {
- const swagger = this.configService.getSwaggerInfo(node.serviceName, node.serviceVersion);
- const swaggerDefinition = this.configService.getDefinition(swagger, node.responses[0].schema.$ref);
- this.loadParamsBySwaggerDefinition(responseItem, swagger, <SwaggerModelSimple>swaggerDefinition);
+ const swagger = this.restService.getSwaggerInfo(node.restConfigId);
+ const SwaggerReferenceObject = node.responses[0].schema as SwaggerReferenceObject;
+ const swaggerDefinition = this.restService.getDefinition(swagger, SwaggerReferenceObject.$ref);
+ this.loadParamsBySwaggerDefinition(responseItem, swagger, swaggerDefinition);
}
}
return item;
}
- private createStatusCodeTreeViewItem(nodeId: string): PlanTreeviewItem {
- return new PlanTreeviewItem('statusCode', `[${nodeId}].[statusCode]`, []);
- }
-
- private createResponseTreeViewItem(nodeId: string): PlanTreeviewItem {
- return new PlanTreeviewItem('response', `[${nodeId}].[responseBody]`, []);
- }
-
- private loadParamsBySwaggerDefinition(parentItem: PlanTreeviewItem, swagger: Swagger, definition: SwaggerModelSimple) {
+ private loadParamsBySwaggerDefinition(parentItem: PlanTreeviewItem, swagger: Swagger, definition: any) {
Object.getOwnPropertyNames(definition.properties).map(key => {
const property = definition.properties[key];
const value = `${parentItem.value}.[${key}]`;
const propertyItem = new PlanTreeviewItem(key, value, []);
parentItem.children.push(propertyItem);
+ // reference to swagger.ts function getSchemaObject()
if (property instanceof SwaggerReferenceObject) {
- const propertyDefinition = this.configService.getDefinition(swagger, property.$ref);
- this.loadParamsBySwaggerDefinition(propertyItem, swagger,
- <SwaggerModelSimple>propertyDefinition);
+ // handle reference parameter.
+ const propertyDefinition = this.restService.getDefinition(swagger, property.$ref);
+ this.loadParamsBySwaggerDefinition(propertyItem, swagger, propertyDefinition);
+ } else if (property instanceof SwaggerModelSimple) {
+ // handle object parameter.
+ this.loadParamsBySwaggerDefinition(propertyItem, swagger, property);
+ } else {
+ // skip
}
return propertyItem;
});
}
+ private createStatusCodeTreeViewItem(nodeId: string): PlanTreeviewItem {
+ return new PlanTreeviewItem('statusCode', `[${nodeId}].[statusCode]`, []);
+ }
+
+ private createResponseTreeViewItem(nodeId: string): PlanTreeviewItem {
+ return new PlanTreeviewItem('response', `[${nodeId}].[responseBody]`, []);
+ }
+
public getPreNodes(nodeId: string, preNodes: WorkflowNode[]) {
const preNode4CurrentNode = [];
this.getProcess().forEach(node => {
@@ -201,7 +386,7 @@ export class ModelService { }
public isPreNode(preNode: WorkflowNode, id: string): boolean {
- const targetNode = preNode.sequenceFlows.find(connection => connection.targetRef === id);
+ const targetNode = preNode.connection.find(connection => connection.targetRef === id);
return targetNode !== undefined;
}
@@ -210,15 +395,62 @@ export class ModelService { }
private createId() {
- const idSet = new Set();
- this.getProcess().forEach(node => idSet.add(node.id));
+ const nodeMap = this.getNodeMap();
- for (let i = 0; i < idSet.size; i++) {
- if (!idSet.has('node' + i)) {
- return 'node' + i;
+ for (let i = 0; i < nodeMap.size; i++) {
+ const key = 'node' + i;
+ if (!nodeMap.get(key)) {
+ return key;
}
}
- return 'node' + idSet.size;
+ return 'node' + nodeMap.size;
+ }
+
+ public getChildrenNodes(parentId: string): WorkflowNode[] {
+ if (!parentId || parentId === this.rootNodeId) {
+ return this.planModel.nodes;
+ } else {
+ const node = this.getNodeMap().get(parentId);
+ if (node.type === 'subProcess') {
+ return (<SubProcess>node).children;
+ } else {
+ return [];
+ }
+ }
+ }
+
+ public changeParent(id: string, originalParentId: string, targetParentId: string) {
+ if (originalParentId === targetParentId) {
+ return;
+ }
+
+ const node: WorkflowNode = this.deleteNode(originalParentId, id);
+ node.parentId = targetParentId;
+
+ if (targetParentId) {
+ this.addChild(targetParentId, node);
+ } else {
+ this.planModel.nodes.push(node);
+ }
+ }
+
+ public updatePosition(id: string, left: number, top: number, width: number, height: number) {
+ const node = this.getNodeMap().get(id);
+ node.position.left = left;
+ node.position.top = top;
+ node.position.width = width;
+ node.position.height = height;
+ }
+
+ public isDescendantNode(node: WorkflowNode, descendantId: string): boolean {
+ if (NodeType[NodeType.subProcess] !== node.type) {
+ return false;
+ }
+ const tmp = (<SubProcess>node).children.find(child => {
+ return child.id === descendantId || (NodeType[NodeType.subProcess] === child.type && this.isDescendantNode(<SubProcess>child, descendantId));
+ });
+
+ return tmp !== undefined;
}
}
diff --git a/sdc-workflow-designer-ui/src/app/services/rest.service.ts b/sdc-workflow-designer-ui/src/app/services/rest.service.ts new file mode 100644 index 00000000..db69d78b --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/services/rest.service.ts @@ -0,0 +1,168 @@ +/*******************************************************************************
+ * Copyright (c) 2017 ZTE Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * ZTE - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+import { Injectable } from '@angular/core';
+import { Http, RequestOptionsArgs } from '@angular/http';
+import { Observable } from 'rxjs/Rx';
+import { isNullOrUndefined } from 'util';
+
+import { SwaggerMethod } from '../model/swagger';
+import { SwaggerResponse } from '../model/swagger';
+import { Swagger, SwaggerSchemaObject } from '../model/swagger';
+import { RestConfig } from '../model/rest-config';
+import { HttpService } from '../util/http.service';
+import { BroadcastService } from './broadcast.service';
+
+@Injectable()
+export class RestService {
+
+ private restConfigs: RestConfig[] = [];
+ private runtimeURL = '/openoapi/catalog/v1/sys/config';
+ private msbPublishServiceURL = '/api/msdiscover/v1/publishservicelist';
+
+ constructor(private broadcastService: BroadcastService, private http: Http) {
+ // this.initSwaggerInfoByMSB();
+ }
+
+ // public addRestConfig(): RestConfig {
+ // let index = 0;
+ // this.restConfigs.forEach(config => {
+ // const currentId = parseInt(config.id);
+ // if (currentId > index) {
+ // index = currentId;
+ // }
+ // });
+
+ // index += 1;
+
+ // const restConfig = new RestConfig(index.toString(), 'new Config', '', '', false);
+ // this.restConfigs.push(restConfig);
+
+ // return restConfig;
+ // }
+
+ // public initSwaggerInfo(restConfig: RestConfig) {
+ // if (restConfig.dynamic && restConfig.definition) {
+ // this.getDynamicSwaggerInfo(restConfig.definition).subscribe(response => restConfig.swagger = new Swagger(response));
+ // } else {
+ // restConfig.swagger = new Swagger(restConfig.swagger);
+ // }
+ // }
+
+ public getRestConfigs() {
+ return this.restConfigs;
+ }
+
+ // public getDynamicSwaggerInfo(url: string): Observable<any> {
+ // const options: any = {
+ // headers: {
+ // Accept: 'application/json',
+ // },
+ // };
+ // return this.httpService.get(url, options);
+ // }
+
+ public getSwaggerInfo(id: string): Swagger {
+ const restConfig = this.restConfigs.find(tmp => tmp.id === id);
+ return restConfig === undefined ? undefined : restConfig.swagger;
+ }
+
+ public getResponseParameters(swagger: Swagger, interfaceUrl: string, operation: string): SwaggerResponse[] {
+ const path = swagger.paths[interfaceUrl];
+ const method: SwaggerMethod = path[operation];
+ let responses: SwaggerResponse[] = [];
+
+ for (const key of Object.keys(method.responses)) {
+ if (key.startsWith('20') && method.responses[key].schema && method.responses[key].schema.$ref) {
+ let response: SwaggerResponse = method.responses[key];
+ responses.push(response);
+ }
+ }
+
+ return responses;
+ }
+
+ public getDefinition(swagger: Swagger, position: string): SwaggerSchemaObject {
+ const definitionName = position.substring('#/definitions/'.length);
+
+ return swagger.definitions[definitionName];
+ }
+
+ private initSwaggerInfoByMSB(): void {
+ const options: any = {
+ headers: {
+ Accept: 'application/json',
+ }
+ };
+ let restConfigs = this.restConfigs;
+ this.http.get(this.runtimeURL).subscribe(runtimeResponse => {
+ const tenant = runtimeResponse.json().tenant;
+ console.log('Current namespace is:' + tenant);
+ this.http.get(this.msbPublishServiceURL, { params: { namespace: tenant } }).subscribe(serviceResponse => {
+ if (!Array.isArray(serviceResponse.json())) {
+ return;
+ }
+ const services = serviceResponse.json();
+ const protocel = location.protocol.slice(0, location.protocol.length - 1);
+ const swaggerObservableArray: Observable<any>[] = [];
+ services.forEach(serviceInfo => {
+ if ('REST' === serviceInfo.protocol && protocel === serviceInfo.publish_protocol) {
+ // this service don't have sawgger file.
+ if ('/activiti-rest' !== serviceInfo.publish_url) {
+ const id = serviceInfo.serviceName + '.' + serviceInfo.version;
+ restConfigs.push(new RestConfig(id, serviceInfo.serviceName, serviceInfo.version, serviceInfo.publish_url));
+ let swaggerUrl = '';
+ if (undefined !== serviceInfo.swagger_url && '' !== serviceInfo.swagger_url) {
+ swaggerUrl = serviceInfo.publish_url + '/' + serviceInfo.swagger_url;
+ } else {
+ // default swagger url is: '/swagger.json'
+ swaggerUrl = serviceInfo.publish_url + '/swagger.json';
+ }
+ swaggerObservableArray.push(this.http.get(swaggerUrl, options).timeout(5000).catch((error): Observable<any> => {
+ console.log('Request swagger from:"' + swaggerUrl + '" faild!');
+ return Observable.of(null);
+ }));
+ }
+ }
+ });
+ Observable.forkJoin(swaggerObservableArray).subscribe(
+ responses => {
+ let deleteArray: number[] = [];
+ responses.forEach((response, index) => {
+ // mark http get failed request index or set the swagger into restConfigs
+ if (null === response) {
+ deleteArray.push(index);
+ } else {
+ try {
+ const swagger = response.json();
+ restConfigs[index].swagger = new Swagger(swagger);
+ } catch (e) {
+ deleteArray.push(index);
+ console.warn('Do not support this sawgger file format:' + response.text());
+ }
+ }
+ });
+ console.log('Get all swagger file finish.');
+ // delete failed request from all restConfigs array
+ deleteArray.reverse();
+ deleteArray.forEach(deleteIndex => {
+ restConfigs.splice(deleteIndex, 1);
+ });
+ this.broadcastService.broadcast(this.broadcastService.updateModelRestConfig, restConfigs);
+ console.log('Load all swagger finished.');
+ }
+ );
+ });
+ });
+ }
+}
+
diff --git a/sdc-workflow-designer-ui/src/app/services/workflow.service.ts b/sdc-workflow-designer-ui/src/app/services/workflow.service.ts index aba8aa21..75382269 100644 --- a/sdc-workflow-designer-ui/src/app/services/workflow.service.ts +++ b/sdc-workflow-designer-ui/src/app/services/workflow.service.ts @@ -41,7 +41,7 @@ export class WorkflowService { }
this.broadcastWorkflows();
});
- this.broadcastService.workflow.subscribe(workflow => this.planModel = workflow);
+ this.broadcastService.planModel.subscribe(workflow => this.planModel = workflow);
}
public save(): Observable<boolean> {
|