* ZTE - initial API and implementation and/or initial documentation
*/
-import { AfterViewInit, Component } from '@angular/core';
+import { AfterViewInit, Component, HostListener } from '@angular/core';
import { BroadcastService } from '../../services/broadcast.service';
import { JsPlumbService } from '../../services/jsplumb.service';
import { DataAccessService } from "../../services/data-access/data-access.service";
import { WorkflowService } from "../../services/workflow.service";
import { Workflow } from "../../model/workflow/workflow";
+import { WorkflowProcessService } from "../../services/workflow-process.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
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 workflowService: WorkflowService,
+ private processService: WorkflowProcessService) {
}
ngOnInit(): void {
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.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(): Workflow {
return this.workflowService.workflow;
z-index: 2;\r
}\r
\r
+\r
+.node.active {\r
+ border: 2px solid red !important;\r
+ box-shadow: 2px 2px 19px #444;\r
+ -o-box-shadow: 2px 2px 19px #444;\r
+ -webkit-box-shadow: 2px 2px 19px #444;\r
+ -moz-box-shadow: 2px 2px 19px #fff;\r
+ opacity: 0.9;\r
+}\r
+\r
.node:hover {\r
border: 1px solid #123456;\r
box-shadow: 2px 2px 19px #444;\r
* ZTE - initial API and implementation and/or initial documentation\r
*/\r
-->\r
-<div (dblclick)="showProperties($event)" class="node {{node.type}}" id="{{node.id}}" [style.top]="node.position.top + 'px'"\r
+<div (dblclick)="showProperties($event)" class="node {{node.type}}" id="{{node.id}}"\r
+ (click)="onSelected()"\r
+ [class.active]="active"\r
+ [style.top]="node.position.top + 'px'"\r
[style.left]="node.position.left + 'px'">\r
<div class="name">\r
{{getDisplayName()}}\r
* ZTE - initial API and implementation and/or initial documentation\r
*/\r
\r
-import { Component, AfterViewInit, Input } from '@angular/core';\r
+import { Component, AfterViewInit, Input, OnDestroy } from '@angular/core';\r
\r
import { JsPlumbService } from '../../services/jsplumb.service';\r
import { BroadcastService } from "../../services/broadcast.service";\r
import { WorkflowNode } from "../../model/workflow/workflow-node";\r
+import { Subscription } from "rxjs/Subscription";\r
\r
/**\r
* workflow node component\r
styleUrls: ['./node.component.css'],\r
templateUrl: 'node.component.html',\r
})\r
-export class NodeComponent implements AfterViewInit {\r
+export class NodeComponent implements AfterViewInit, OnDestroy {\r
\r
@Input() public node: WorkflowNode;\r
@Input() public last: boolean;\r
\r
+ public active = false;\r
+ private currentTypeSubscription: Subscription;\r
+ private currentWorkflowSubscription: Subscription;\r
+\r
constructor(private broadcastService: BroadcastService,\r
private jsPlumbService: JsPlumbService) {\r
\r
if(this.last) {\r
this.jsPlumbService.initNode('.node');\r
}\r
+\r
+ this.currentTypeSubscription = this.broadcastService.currentType$.subscribe(type => {\r
+ if (type === 'SequenceFlow') {\r
+ this.active = false;\r
+ }\r
+ });\r
+\r
+ this.currentWorkflowSubscription = this.broadcastService.currentWorkflowNode$.subscribe(activeNode => {\r
+ if (activeNode.id === this.node.id) {\r
+ this.active = true;\r
+ } else {\r
+ this.active = false;\r
+ }\r
+ });\r
+ }\r
+\r
+ public ngOnDestroy() {\r
+ this.currentTypeSubscription.unsubscribe();\r
+ this.currentWorkflowSubscription.unsubscribe();\r
}\r
\r
public showProperties() {\r
}\r
}\r
\r
+ public onSelected() {\r
+ this.broadcastService.broadcast(this.broadcastService.currentWorkflowNode, this.node);\r
+ this.broadcastService.broadcast(this.broadcastService.currentType, 'WorkflowNode');\r
+ }\r
+\r
}\r
public sequenceFlow = new Subject<SequenceFlow>();
public sequenceFlow$ = this.sequenceFlow.asObservable();
+ public currentSequenceFlow = new Subject<SequenceFlow>();
+ public currentSequenceFlow$ = this.currentSequenceFlow.asObservable();
+ public currentWorkflowNode = new Subject<WorkflowNode>();
+ public currentWorkflowNode$ = this.currentWorkflowNode.asObservable();
+ public currentType = new Subject<string>();
+ public currentType$ = this.currentType.asObservable();
+
/**
* broadcast datas
* this method will catch the exceptions for the broadcast
import * as jsp from 'jsplumb';\r
import { WorkflowProcessService } from "./workflow-process.service";\r
import { BroadcastService } from "./broadcast.service";\r
+import { Subscription } from 'rxjs/Subscription';\r
\r
/**\r
* JsPlumbService\r
@Injectable()\r
export class JsPlumbService {\r
public jsplumbInstance;\r
+ public subscriptionMap = new Map<string, Subscription>();\r
\r
constructor(private processService: WorkflowProcessService, private broadcastService: BroadcastService) {\r
this.initJsPlumbInstance();\r
this.jsplumbInstance.bind('connection', info => {\r
this.processService.addSequenceFlow(info.connection.sourceId, info.connection.targetId);\r
\r
- // info.connection.bind('click', connection => {\r
- // this.jsplumbInstance.select({ connections: [connection] }).delete();\r
- // this.processService.deleteSequenceFlow(connection.sourceId, connection.targetId);\r
- // });\r
+ this.subscribe4Connection(info.connection);\r
+\r
+ info.connection.bind('click', connection => {\r
+ const sequenceFlow = this.processService.getSequenceFlow(connection.sourceId, connection.targetId);\r
+ this.broadcastService.broadcast(this.broadcastService.currentSequenceFlow, sequenceFlow);\r
+ this.broadcastService.broadcast(this.broadcastService.currentType, 'SequenceFlow');\r
+ });\r
\r
info.connection.bind('dblclick', connection => {\r
const sequenceFlow = this.processService.getSequenceFlow(connection.sourceId, connection.targetId);\r
\r
}\r
\r
+ private subscribe4Connection(connection: any) {\r
+ const pre = connection.sourceId + connection.targetId;\r
+ let sequenceFlowSubscription = this.subscriptionMap.get(pre + 'sequenceFlowSubscription');\r
+ if (sequenceFlowSubscription && !sequenceFlowSubscription.closed) {\r
+ sequenceFlowSubscription.unsubscribe();\r
+ }\r
+\r
+ sequenceFlowSubscription = this.broadcastService.currentSequenceFlow$.subscribe(currentSequenceFlow => {\r
+ if (currentSequenceFlow.sourceRef === connection.sourceId\r
+ && currentSequenceFlow.targetRef === connection.targetId) {\r
+ connection.setPaintStyle({ stroke: 'red' });\r
+ } else {\r
+ connection.setPaintStyle({ stroke: 'black' });\r
+ }\r
+ });\r
+\r
+ this.subscriptionMap.set(pre + 'sequenceFlowSubscription', sequenceFlowSubscription);\r
+\r
+ let typeSubscription = this.subscriptionMap.get(pre + 'typeSubscription');\r
+ if (typeSubscription && !typeSubscription.closed) {\r
+ typeSubscription.unsubscribe();\r
+ }\r
+ typeSubscription = this.broadcastService.currentType$.subscribe(type => {\r
+ if (type === 'WorkflowNode') {\r
+ connection.setPaintStyle({ stroke: 'black' });\r
+ }\r
+ });\r
+ this.subscriptionMap.set(pre + 'typeSubscription', typeSubscription);\r
+ }\r
+\r
+ private unsubscription4Connection(connectionSelection: any) {\r
+ connectionSelection.each(connection => {\r
+ const pre = connection.sourceId + connection.targetId;\r
+ this.subscriptionMap.get(pre + 'sequenceFlowSubscription').unsubscribe();\r
+ this.subscriptionMap.get(pre + 'typeSubscription').unsubscribe();\r
+ });\r
+ }\r
+\r
public initNode(selectorString: string) {\r
const selector = this.jsplumbInstance.getSelector(selectorString);\r
\r
this.jsplumbInstance.draggable(selector, {\r
- // stop(event) {\r
- // node.position.left = event.pos[0];\r
- // node.position.top = event.pos[1];\r
- // },\r
});\r
\r
this.jsplumbInstance.makeTarget(selector, {\r
public deleteConnect(sourceId: string, targetId: string) {\r
const sourceNode = this.processService.getNodeById(sourceId);\r
const connectionSelection = this.jsplumbInstance.select({ source: sourceId, target: targetId });\r
+ this.unsubscription4Connection(connectionSelection);\r
connectionSelection.delete();\r
}\r
\r
public remove(nodeId: string) {\r
+ // unsubscription4Connection\r
+ const connectionsAsSource = this.jsplumbInstance.select({ source: nodeId });\r
+ this.unsubscription4Connection(connectionsAsSource);\r
+ const connectionsAsTarget = this.jsplumbInstance.select({ target: nodeId });\r
+ this.unsubscription4Connection(connectionsAsTarget);\r
+\r
this.jsplumbInstance.remove(nodeId);\r
}\r
\r