"license": "MIT",
"scripts": {
"ng": "ng",
- "start": "ng serve",
+ "start": "ng serve --host 10.90.74.215 --disable-host-check=true",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
.container {\r
width: 100%;\r
height: 100%;\r
- background-color: cadetblue;\r
}\r
\r
<!--The content below is only a placeholder and can be replaced.-->
+<b4t-toolbar></b4t-toolbar>
+
<div id="container" class="container">
- <b4t-node *ngFor="let node of nodes" [node]="node"></b4t-node>
+ <b4t-node *ngFor="let node of getNodes(); let last = last;" [node]="node" [last]="last"></b4t-node>
</div>
import { Component, AfterViewInit } from '@angular/core';
import { JsPlumbService } from "./services/jsplumb.service";
+import { WorkflowService } from "./services/workflow.service";
+import { WorkflowNode } from "./model/workflow-node";
@Component({
selector: 'app-root',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
- constructor(private jsplumbService: JsPlumbService) {}
+ constructor(private jsplumbService: JsPlumbService, private workflowService: WorkflowService) {}
- public nodes = [
- {
- id: '001',
- name: 'node001',
- top: 50,
- left: 50,
- },
- {
- id: '002',
- name: 'node002',
- top: 250,
- left: 50,
- },
- {
- id: '003',
- name: 'node003',
- top: 140,
- left: 450,
- },
- ];
+ public getNodes(): WorkflowNode[] {
+ return this.workflowService.getNodes();
+ }
ngAfterViewInit(): void {
- this.jsplumbService.initJsPlumbInstance();
- this.jsplumbService.initNode('.node');
+ this.jsplumbService.buttonDroppable();
}
}
import { AppComponent } from './app.component';
import { JsPlumbService } from "./services/jsplumb.service";
import { NodeComponent } from "./components/node/node.component";
+import { ToolbarComponent } from "./components/toolbar/toolbar.component";
+import { WorkflowService } from "./services/workflow.service";
@NgModule({
declarations: [
AppComponent,
NodeComponent,
+ ToolbarComponent,
],
imports: [
BrowserModule
],
- providers: [JsPlumbService],
+ providers: [JsPlumbService, WorkflowService],
bootstrap: [AppComponent]
})
export class AppModule { }
* ZTE - initial API and implementation and/or initial documentation\r
*/\r
-->\r
-<div class="node" [style.top]="node.top + 'px'"\r
- [style.left]="node.left + 'px'">\r
+<div class="node" [style.top]="node.top + 'px'" [style.left]="node.left + 'px'">\r
<div>{{node.name}}</div>\r
<div class="anchor anchors anchor-left">\r
<span class="left">\r
styleUrls: ['./node.component.css'],\r
templateUrl: 'node.component.html',\r
})\r
-export class NodeComponent {\r
+export class NodeComponent implements AfterViewInit {\r
+\r
@Input() public node: Node;\r
+ @Input() public last: boolean;\r
\r
constructor(private jsPlumbService: JsPlumbService) {\r
\r
}\r
\r
+ ngAfterViewInit(): void {\r
+ if(this.last) {\r
+ this.jsPlumbService.initNode('.node');\r
+ }\r
+ }\r
+\r
}\r
--- /dev/null
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ * ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+.toolbar {\r
+ padding: 10px 30px 0px 10px;\r
+ position: fixed;\r
+ top: 0px;\r
+ left: 0px;\r
+ width: 100%;\r
+ z-index: 4;\r
+}\r
+\r
+button {\r
+ transition: all 0s;\r
+ height: 30px;\r
+}\r
--- /dev/null
+<!--\r
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ * ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+-->\r
+<div class="toolbar">\r
+ <div class="row">\r
+ <button type="button" class="btn btn-secondary item ui-draggable" [attr.nodeType]="'startEvent'">\r
+ <span>startEvent</span>\r
+ </button>\r
+ <button type="button" class="btn btn-secondary item ui-draggable" [attr.nodeType]="'endEvent'">\r
+ <span>endEvent</span>\r
+ </button>\r
+ </div>\r
+</div>\r
--- /dev/null
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ * ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+import { AfterViewInit, Component } from '@angular/core';\r
+\r
+import { JsPlumbService } from '../../services/jsplumb.service';\r
+\r
+/**\r
+ * toolbar component contains some basic operations(save) and all of the supported workflow nodes.\r
+ * The supported nodes can be dragged to container component. which will add a new node to the workflow.\r
+ */\r
+@Component({\r
+ selector: 'b4t-toolbar',\r
+ templateUrl: 'toolbar.component.html',\r
+ styleUrls: ['./toolbar.component.css']\r
+})\r
+export class ToolbarComponent implements AfterViewInit {\r
+\r
+ constructor(private jsPlumbService: JsPlumbService) {\r
+ }\r
+\r
+ public ngAfterViewInit() {\r
+ this.jsPlumbService.buttonDraggable();\r
+ }\r
+\r
+}\r
--- /dev/null
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ * ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+import { Injectable } from '@angular/core';\r
+\r
+/**\r
+ * WorkflowNode\r
+ */\r
+export class WorkflowNode {\r
+ constructor(public id: string, public name: string, public type: string, public top: number, public left: number) {}\r
+}\r
\r
import { Injectable } from '@angular/core';\r
import * as jsp from 'jsplumb';\r
+import { WorkflowService } from "./workflow.service";\r
\r
/**\r
* JsPlumbService\r
export class JsPlumbService {\r
private jsplumbInstance;\r
\r
- constructor() {\r
-\r
+ constructor(private workflowService: WorkflowService) {\r
+ this.initJsPlumbInstance();\r
}\r
\r
\r
\r
// add connection to model data while a new connection is build\r
this.jsplumbInstance.bind('connection', info => {\r
- this.jsplumbInstance.bind('connection', info => {\r
-\r
- info.connection.bind('click', connection => {\r
- this.jsplumbInstance.select({ connections: [connection] }).delete();\r
- });\r
- });\r
- \r
+ info.connection.bind('click', connection => {\r
+ this.jsplumbInstance.select({ connections: [connection] }).delete();\r
+ });\r
});\r
\r
}\r
maxConnections: -1,\r
});\r
\r
- }
+ }\r
+\r
+ public buttonDraggable() {\r
+ const selector = this.jsplumbInstance.getSelector('.toolbar .item');\r
+ this.jsplumbInstance.draggable(selector,\r
+ {\r
+ scope: 'btn',\r
+ clone: true,\r
+ });\r
+ }\r
+\r
+ public buttonDroppable() {\r
+ const selector = this.jsplumbInstance.getSelector('.container');\r
+ this.jsplumbInstance.droppable(selector, {\r
+ scope: 'btn',\r
+ drop: event => {\r
+ const el = this.jsplumbInstance.getSelector(event.drag.el);\r
+ const type = el.attributes.nodeType.value;\r
+ const left = event.e.clientX - event.drop.position[0];\r
+ const top = event.e.clientY - event.drop.position[1];\r
+\r
+ this.workflowService.addNode(type, type, top, left);\r
+ },\r
+ });\r
+ }\r
+\r
}\r
--- /dev/null
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ * ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+import { Injectable } from '@angular/core';\r
+import { WorkflowNode } from "../model/workflow-node";\r
+\r
+/**\r
+ * WorkflowService\r
+ * provides all of the operations about workflow operations.\r
+ */\r
+@Injectable()\r
+export class WorkflowService {\r
+ public nodes: WorkflowNode[] = [];\r
+\r
+ public getNodes(): WorkflowNode[] {\r
+ return this.nodes;\r
+ }\r
+\r
+ public addNode(name: string, type: string, top: number, left: number) {\r
+ this.nodes.push(new WorkflowNode(this.createId(), name, type, top, left));\r
+ }\r
+\r
+ public deleteNode(nodeId: string): WorkflowNode {\r
+ // delete current node\r
+ const index = this.nodes.findIndex(node => node.id === nodeId);\r
+ if (index !== -1) {\r
+ const node = this.nodes.splice(index, 1)[0];\r
+ return node;\r
+ }\r
+\r
+ return undefined;\r
+ }\r
+\r
+ public getNode(sourceId: string): WorkflowNode {\r
+ return this.nodes.find(node => node.id === sourceId);\r
+ }\r
+\r
+ private createId() {\r
+ const idSet = new Set();\r
+ this.nodes.forEach(node => idSet.add(node.id));\r
+\r
+ for (let i = 0; i < idSet.size; i++) {\r
+ if (!idSet.has('node' + i)) {\r
+ return 'node' + i;\r
+ }\r
+ }\r
+\r
+ return 'node' + idSet.size;\r
+ }\r
+}\r
<head>
<meta charset="utf-8">
<title>Workflow Designer</title>
- <base href="/">
+ <base href="/lvbo">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
body, html {
height: 100%;
margin: 0px;
+ background-color: cadetblue;
}