summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArundathi Patil <arundpil@in.ibm.com>2019-10-11 12:33:57 +0530
committerArundathi Patil <arundpil@in.ibm.com>2019-10-11 12:34:29 +0530
commitd71ba83a6075950877963fef084a5f6e4aa598ba (patch)
treecdc6b378c65b13ee0860b5da398a74bf45d18e2b
parentce9b0657f0614c993c36381c0ab301d7b4337db5 (diff)
JointJS Prototype
Added JointJS POC Issue-ID: CCSDK-1765 Change-Id: Ia8a6e913e3d4f10f3fdc0e1ec377304e49879240 Signed-off-by: Arundathi Patil <arundpil@in.ibm.com>
-rw-r--r--cds-ui/client/JointJS-POC-In-Progress/app-routing.module.ts10
-rw-r--r--cds-ui/client/JointJS-POC-In-Progress/app.component.html31
-rw-r--r--cds-ui/client/JointJS-POC-In-Progress/app.component.scss81
-rw-r--r--cds-ui/client/JointJS-POC-In-Progress/app.component.spec.ts35
-rw-r--r--cds-ui/client/JointJS-POC-In-Progress/app.component.ts869
-rw-r--r--cds-ui/client/JointJS-POC-In-Progress/app.module.ts24
6 files changed, 1050 insertions, 0 deletions
diff --git a/cds-ui/client/JointJS-POC-In-Progress/app-routing.module.ts b/cds-ui/client/JointJS-POC-In-Progress/app-routing.module.ts
new file mode 100644
index 000000000..d425c6f56
--- /dev/null
+++ b/cds-ui/client/JointJS-POC-In-Progress/app-routing.module.ts
@@ -0,0 +1,10 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+const routes: Routes = [];
+
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ exports: [RouterModule]
+})
+export class AppRoutingModule { }
diff --git a/cds-ui/client/JointJS-POC-In-Progress/app.component.html b/cds-ui/client/JointJS-POC-In-Progress/app.component.html
new file mode 100644
index 000000000..da05dd563
--- /dev/null
+++ b/cds-ui/client/JointJS-POC-In-Progress/app.component.html
@@ -0,0 +1,31 @@
+<!-- <div id="myholder"></div> -->
+<div style="background-color: black; color: white; height: 75px; width:100%; font-size: 2em; margin-bottom: 3px">
+ CDS DESIGNER POC
+ <button (click)="convertGraphToJson()">Save</button>
+</div>
+<div style="display: flex;flex-direction:row; height: 700PX">
+ <div id="stencil" style="width: 30%;height: 100%;border: 1px solid; border-radius:0.5em; background-color: gainsboro"></div>
+ <div style="width: 70%; height: 100%;">
+ <div style="position: fixed;width: 200px;background-color: gainsboro;height: 36px;z-index: 2;">
+ <button *ngIf="!sourceMode" style="border-radius: 0.5em;width: 6em;height: 2.5em;border: 2px solid black;" (click)="convertGraphToJson()">Source</button>
+ <button *ngIf="sourceMode" style="border-radius: 0.5em;width: 6em;height: 2.5em;border: 2px solid black;" (click)="convertJsonToGraph()">Graph</button>
+ <i (click) ="zoomIn()" class="fa fa-search-plus" aria-hidden="true"></i>
+ <i (click) ="zoomOut()" class="fa fa-search-minus" aria-hidden="true"></i>
+ </div>
+ <div [hidden]="sourceMode" id="paper" style="height: 100%;"></div>
+ <div id="sourceJson" [hidden]="!sourceMode"style="width: 100%; height: 100%;"><textarea style="margin-top: 4em;
+ width: 100%;
+ height: 100%;">{{grapJson}}</textarea></div>
+ </div>
+ <div id="propertyPanel" style="width: 20%; height: 100%; background-color: white">
+ <div style="background-color: gainsboro;height:28px">Attributes</div>
+ <div style="height: 100px;padding: 10px">
+ Action Name<br/>
+ <input type="text" [(ngModel)]="selectedElement.attributes.attrs.label.text" (change)="setNewValue($event)"/>
+ </div>
+ <div>
+ <div style="background-color: gainsboro;height:28px">Input</div>
+
+ </div>
+ </div>
+</div>
diff --git a/cds-ui/client/JointJS-POC-In-Progress/app.component.scss b/cds-ui/client/JointJS-POC-In-Progress/app.component.scss
new file mode 100644
index 000000000..68d06fbe7
--- /dev/null
+++ b/cds-ui/client/JointJS-POC-In-Progress/app.component.scss
@@ -0,0 +1,81 @@
+#stencil {
+ position: relative;
+ border: 1px solid gray;
+ display: inline-block;
+ background: transparent;
+ overflow: hidden;
+}
+#stencil svg {
+ background: transparent;
+}
+#stencil svg .link {
+ z-index: 2;
+}
+.html-element {
+ position: absolute;
+ background: #3498DB;
+ /* Make sure events are propagated to the JointJS element so, e.g. dragging works.*/
+ pointer-events: none;
+ -webkit-user-select: none;
+ border-radius: 4px;
+ border: 2px solid #2980B9;
+ box-shadow: inset 0 0 5px black, 2px 2px 1px gray;
+ padding: 5px;
+ box-sizing: border-box;
+ z-index: 2;
+}
+.html-element select,
+.html-element input,
+.html-element button {
+ /* Enable interacting with inputs only. */
+ pointer-events: auto;
+}
+.html-element button.delete {
+ color: white;
+ border: none;
+ background-color: #C0392B;
+ border-radius: 20px;
+ width: 15px;
+ height: 15px;
+ line-height: 15px;
+ text-align: middle;
+ position: absolute;
+ top: -15px;
+ left: -15px;
+ padding: 0;
+ margin: 0;
+ font-weight: bold;
+ cursor: pointer;
+}
+.html-element button.delete:hover {
+ width: 20px;
+ height: 20px;
+ line-height: 20px;
+}
+.html-element select {
+ position: absolute;
+ right: 2px;
+ bottom: 28px;
+}
+.html-element input {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ border: none;
+ color: #333;
+ padding: 5px;
+ height: 16px;
+}
+.html-element label {
+ color: #333;
+ text-shadow: 1px 0 0 lightgray;
+ font-weight: bold;
+}
+.html-element span {
+ position: absolute;
+ top: 2px;
+ right: 9px;
+ color: white;
+ font-size: 10px;
+} \ No newline at end of file
diff --git a/cds-ui/client/JointJS-POC-In-Progress/app.component.spec.ts b/cds-ui/client/JointJS-POC-In-Progress/app.component.spec.ts
new file mode 100644
index 000000000..8de310a78
--- /dev/null
+++ b/cds-ui/client/JointJS-POC-In-Progress/app.component.spec.ts
@@ -0,0 +1,35 @@
+import { TestBed, async } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { AppComponent } from './app.component';
+
+describe('AppComponent', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ RouterTestingModule
+ ],
+ declarations: [
+ AppComponent
+ ],
+ }).compileComponents();
+ }));
+
+ it('should create the app', () => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app).toBeTruthy();
+ });
+
+ it(`should have as title 'jointJS-designer'`, () => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app.title).toEqual('jointJS-designer');
+ });
+
+ it('should render title in a h1 tag', () => {
+ const fixture = TestBed.createComponent(AppComponent);
+ fixture.detectChanges();
+ const compiled = fixture.debugElement.nativeElement;
+ expect(compiled.querySelector('h1').textContent).toContain('Welcome to jointJS-designer!');
+ });
+});
diff --git a/cds-ui/client/JointJS-POC-In-Progress/app.component.ts b/cds-ui/client/JointJS-POC-In-Progress/app.component.ts
new file mode 100644
index 000000000..289a57766
--- /dev/null
+++ b/cds-ui/client/JointJS-POC-In-Progress/app.component.ts
@@ -0,0 +1,869 @@
+declare var require: any
+import { Component, OnInit } from '@angular/core';
+import * as $ from 'jquery';
+import * as _ from 'lodash';
+const joint = require('../../node_modules/jointjs/dist/joint.js');
+
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.scss']
+})
+export class AppComponent implements OnInit {
+ title = 'jointJS-designer';
+
+ public graph: any;
+ public paper: any;
+ public rect: any;
+ public rect2: any;
+ public link: any;
+
+ public stencilGraph: any;
+ public stencilPaper: any;
+
+ public selectedElement = {
+ attributes: {
+ attrs: {
+ label: {
+ text: 'abc'
+ }
+ }
+ }
+ };
+
+ grapJson: any;
+ sourceMode = false;
+
+ constructor() {
+
+ }
+
+ ngOnInit() {
+ // this.creatElementWithPorts();
+ // this.dragCopyPlainElements();
+ this.sourceMode = false;
+ this.dragCopyElementsWithPort();
+ // this.newDragCopy();
+
+ this.createContainerElements();
+ }
+
+ creatElementWithPorts() {
+ // working code
+
+ // create graph
+ let elementList: any[] = [];
+ // this.graph = new joint.dia.Graph;
+
+ // // create paper
+ // this.paper = new joint.dia.Paper({
+ // el: document.getElementById('paper'),
+ // width: 1000,
+ // height: 1000,
+ // model: this.graph,
+ // gridSize: 2,
+ // drawGrid: true
+ // });
+
+ // this.paper.setGrid({
+ // name: 'dot',
+ // args:
+ // { color: 'black', thickness: 2, scaleFactor: 8 }
+
+ // }).drawGrid();
+
+ // create element
+ this.rect = new joint.shapes.basic.Rect({
+ position: { x: 100, y: 30 },
+ size: { width: 100, height: 100 },
+ attrs: { rect: { fill: 'white' }, text: { text: 'my box', fill: 'white' } }
+ });
+ this.rect.translate(100, 50);
+ elementList.push(this.rect);
+
+ this.rect.position(10, 10);
+ // clone element
+ // this.rect2 = this.rect.clone();
+ // this.rect2.translate(180);
+ // elementList.push(this.rect2);
+
+ // Create link
+ // this.link = new joint.dia.Link({
+ // source: { id: this.rect.id },
+ // target: { id: this.rect2.id }
+ // });
+
+
+ // create circle
+ var circle = new joint.shapes.standard.Circle();
+ circle.resize(100, 100);
+ circle.position(180, 10);
+ circle.attr('root/title', 'joint.shapes.standard.Circle');
+ circle.attr('label/text', 'Circle');
+ circle.attr('body/fill', 'lightblue');
+ elementList.push(circle);
+
+ // create link
+ var ellipse = new joint.shapes.standard.Ellipse();
+ ellipse.resize(150, 100);
+ ellipse.position(180, 150);
+ ellipse.attr('root/title', 'joint.shapes.standard.Ellipse');
+ ellipse.attr('label/text', 'Ellipse');
+ ellipse.attr('body/fill', 'lightblue');
+ elementList.push(ellipse);
+
+ // rectangle with header
+ var headeredRectangle = new joint.shapes.standard.HeaderedRectangle();
+ headeredRectangle.resize(150, 100);
+ headeredRectangle.position(10, 280);
+ headeredRectangle.attr('root/title', 'joint.shapes.standard.HeaderedRectangle');
+ headeredRectangle.attr('header/fill', 'lightgray');
+ headeredRectangle.attr('headerText/text', 'Header');
+ headeredRectangle.attr('bodyText/text', 'Headered\nRectangle');
+ elementList.push(headeredRectangle);
+
+ let m1 = new joint.shapes.devs.Model({
+ position: { x: 200, y: 280 },
+ size: { width: 90, height: 90 },
+ inPorts: ['in1', 'in2'],
+ outPorts: ['out', 'out2'],
+ ports: {
+ groups: {
+ 'in': {
+ attrs: {
+ '.port-body': {
+ fill: '#16A085'
+ }
+ }
+ },
+ 'out': {
+ attrs: {
+ '.port-body': {
+ fill: '#E74C3C'
+ }
+ }
+ }
+ }
+ },
+ attrs: {
+ '.label': { text: 'Model', 'ref-x': .5, 'ref-y': .2 },
+ rect: { fill: 'white' }
+ }
+ });
+ elementList.push(m1);
+
+ //container element
+ let c1 = new joint.shapes.devs.Coupled({
+ position: {
+ x: 150,
+ y: 470
+ },
+ size: {
+ width: 200,
+ height: 200
+ }
+ });
+
+ c1.set('inPorts', ['in']);
+ c1.set('outPorts', ['out 1', 'out 2']);
+ c1.attr({
+ '.body': {
+ 'rx': 6,
+ 'ry': 6
+ }
+});
+ elementList.push(c1);
+ // circle.position(10, 150);
+ var a1 = new joint.shapes.devs.Atomic({
+ position: {
+ x: 10,
+ y: 150
+ },
+ inPorts: ['xy'],
+ outPorts: ['x', 'y']
+ });
+
+ a1.attr({
+ '.body': {
+ 'rx': 6,
+ 'ry': 6
+ }
+ });
+
+ elementList.push(a1);
+
+
+ return elementList;
+ }
+
+ dragCopyPlainElements() {
+ // Canvas where sape are dropped
+ this.graph = new joint.dia.Graph,
+ this.paper = new joint.dia.Paper({
+ el: $('#paper'),
+ model: this.graph
+ });
+
+ // Canvas from which you take shapes
+ this.stencilGraph = new joint.dia.Graph,
+ this.stencilPaper = new joint.dia.Paper({
+ el: $('#stencil'),
+ height: 60,
+ model: this.stencilGraph,
+ interactive: false
+ });
+
+ var r1 = new joint.shapes.basic.Rect({
+ position: {
+ x: 10,
+ y: 10
+ },
+ size: {
+ width: 100,
+ height: 40
+ },
+ attrs: {
+ text: {
+ text: 'Rect1'
+ }
+ }
+ });
+ var r2 = new joint.shapes.basic.Rect({
+ position: {
+ x: 120,
+ y: 10
+ },
+ size: {
+ width: 100,
+ height: 40
+ },
+ attrs: {
+ text: {
+ text: 'Rect2'
+ }
+ }
+ });
+ this.stencilGraph.addCells([r1, r2]);
+
+ let _this = this;
+
+ this.stencilPaper.on('cell:pointerdown', function (cellView, e, x, y) {
+ $('body').append('<div id="flyPaper" style="position:fixed;z-index:100;opacity:.7;pointer-event:none;"></div>');
+ var flyGraph = new joint.dia.Graph,
+ flyPaper = new joint.dia.Paper({
+ el: $('#flyPaper'),
+ model: flyGraph,
+ interactive: false
+ }),
+ flyShape = cellView.model.clone(),
+ pos = cellView.model.position(),
+ offset = {
+ x: x - pos.x,
+ y: y - pos.y
+ };
+
+ flyShape.position(0, 0);
+ flyGraph.addCell(flyShape);
+ $("#flyPaper").offset({
+ left: e.pageX - offset.x,
+ top: e.pageY - offset.y
+ });
+ $('body').on('mousemove.fly', function (e) {
+ $("#flyPaper").offset({
+ left: e.pageX - offset.x,
+ top: e.pageY - offset.y
+ });
+ });
+ $('body').on('mouseup.fly', function (e) {
+ var x = e.pageX,
+ y = e.pageY,
+ target = _this.paper.$el.offset();
+
+ // Dropped over paper ?
+ if (x > target.left && x < target.left + _this.paper.$el.width() && y > target.top && y < target.top + _this.paper.$el.height()) {
+ var s = flyShape.clone();
+ s.position(x - target.left - offset.x, y - target.top - offset.y);
+ _this.graph.addCell(s);
+ }
+ $('body').off('mousemove.fly').off('mouseup.fly');
+ flyShape.remove();
+ $('#flyPaper').remove();
+ });
+ })
+ }
+
+ dragCopyElementsWithPort() {
+ // Canvas where sape are dropped
+
+ this.graph = new joint.dia.Graph,
+ this.paper = new joint.dia.Paper({
+ el: $('#paper'),
+ model: this.graph,
+ height: 700,
+ width: 1000,
+ gridSize: 2,
+ drawGrid: true
+ });
+
+ // create paper
+ // this.paper = new joint.dia.Paper({
+ // el: document.getElementById('paper'),
+ // width: 1000,
+ // height: 1000,
+ // model: this.graph,
+ // gridSize: 2,
+ // drawGrid: true
+ // });
+
+ this.paper.setGrid({
+ name: 'dot',
+ args:
+ { color: 'black', thickness: 2, scaleFactor: 8 }
+
+ }).drawGrid();
+
+ // Canvas from which you take shapes
+ this.stencilGraph = new joint.dia.Graph,
+ this.stencilPaper = new joint.dia.Paper({
+ el: $('#stencil'),
+ height: 700,
+ width: 382,
+ model: this.stencilGraph,
+ interactive: false
+ });
+
+ let elementWithPort = this.creatElementWithPorts();
+ // let elementWithPort = this.createCustomElement();
+ // let elementWithPort = this.myCustomElementGenerator();
+
+
+
+ elementWithPort.forEach(element => {
+ this.stencilGraph.addCell(element);
+ });
+
+ let _this = this;
+ this.stencilPaperEventListeners(_this);
+ this.drawAreapaperEventListerners();
+ }
+
+ resetAll(paper) {
+ this.paper.drawBackground({
+ color: 'white'
+ })
+
+ var elements = this.paper.model.getElements();
+ for (var i = 0, ii = elements.length; i < ii; i++) {
+ var currentElement = elements[i];
+ currentElement.attr('body/stroke', 'black');
+ }
+
+ var links = this.paper.model.getLinks();
+ for (var j = 0, jj = links.length; j < jj; j++) {
+ var currentLink = links[j];
+ currentLink.attr('line/stroke', 'black');
+ currentLink.label(0, {
+ attrs: {
+ body: {
+ stroke: 'black'
+ }
+ }
+ })
+ }
+ }
+
+ onDrag(evt) {
+ // transform client to paper coordinates
+ var p = evt.data.paper.snapToGrid({
+ x: evt.clientX,
+ y: evt.clientY
+ });
+ // manually execute the linkView mousemove handler
+ evt.data.view.pointermove(evt, p.x, p.y);
+ }
+
+ onDragEnd(evt) {
+ // manually execute the linkView mouseup handler
+ evt.data.view.pointerup(evt);
+ $(document).off('.example');
+ }
+
+ stencilPaperEventListeners(_this) {
+ this.stencilPaper.on('cell:pointerdown', function (cellView, e, x, y) {
+ $('body').append('<div id="flyPaper" style="position:fixed;z-index:100;opacity:.7;pointer-event:none;"></div>');
+ var flyGraph = new joint.dia.Graph,
+ flyPaper = new joint.dia.Paper({
+ el: $('#flyPaper'),
+ model: flyGraph,
+ interactive: true
+ }),
+ flyShape = cellView.model.clone(),
+ pos = cellView.model.position(),
+ offset = {
+ x: x - pos.x,
+ y: y - pos.y
+ };
+
+ flyShape.position(0, 0);
+ flyGraph.addCell(flyShape);
+ $("#flyPaper").offset({
+ left: e.pageX - offset.x,
+ top: e.pageY - offset.y
+ });
+ $('body').on('mousemove.fly', function (e) {
+ $("#flyPaper").offset({
+ left: e.pageX - offset.x,
+ top: e.pageY - offset.y
+ });
+ });
+ let elementabove, elementBelow;
+ $('body').on('mouseup.fly', function (e) {
+ console.log(this);
+ var x = e.pageX,
+ y = e.pageY,
+ target = _this.paper.$el.offset();
+
+ // Dropped over paper ?
+ if (x > target.left && x < target.left + _this.paper.$el.width() && y > target.top && y < target.top + _this.paper.$el.height()) {
+ var s = flyShape.clone();
+
+ // var coordinates = new g.Point(x, y);
+ // elementabove = s;
+ // elementBelow = _this.paper.model.findModelsFromPoint(coordinates).find(function(el) {
+ // return (el.id !== elementabove.id);
+ // });
+ // elementBelow =_this.paper.findModelsFromPoint(coordinates).find(function(el) {
+ // return (el.id !== elementabove.id);
+ // });
+ // elementBelow.embed(elementabove);
+
+ s.position(x - target.left - offset.x, y - target.top - offset.y);
+ _this.graph.addCell(s);
+ // let elementssss = (_this.graph.getElements());
+ // console.log("elementsss", elementssss);
+ // let elementBelow = elementssss[0];
+ // let elementAbove;
+ // if(elementssss[1]) {
+ // elementAbove = elementssss[1];
+ // elementBelow.embed(elementabove);
+ // }
+ }
+ $('body').off('mousemove.fly').off('mouseup.fly');
+ flyShape.remove();
+ $('#flyPaper').remove();
+ });
+ _this.paper.on('mouse')
+ })
+ }
+
+ drawAreapaperEventListerners() {
+ // create event listerners
+ let _this = this;
+ this.paper.on('element:pointerdblclick', function (elementView) {
+ _this.resetAll(this);
+ _this.selectedElement = elementView.model;
+ var currentElement = elementView.model;
+ currentElement.attr('body/stroke', 'orange');
+ // currentElement.attr('label/text', "abc");
+ });
+
+ this.paper.on('blank:pointerdblclick', function () {
+ _this.resetAll(this);
+
+ this.drawBackground({
+ color: 'orange'
+ });
+ });
+
+ this.paper.on('link:pointerclick', function (linkView) {
+ _this.resetAll(this);
+ let currentElement = linkView.model;
+ currentElement.appendLabel({
+ attrs: {
+ text: {
+ text: "Hello to new link!"
+ }
+ }
+ });
+
+ });
+
+
+ this.paper.on('blank:pointerdown', function (evt, x, y) {
+ let linkView = this.getDefaultLink()
+ .set({
+ 'source': { x: x, y: y },
+ 'target': { x: x, y: y }
+ })
+ .addTo(this.model)
+ .findView(this);
+ linkView.startArrowheadMove('target');
+
+ $(document).on({
+ 'mousemove.example': _this.onDrag,
+ 'mouseup.example': _this.onDragEnd
+ }, {
+ // shared data between listeners
+ view: linkView,
+ paper: this
+ });
+ });
+
+ this.paper.on({
+ // 'element:pointerdown': function(elementView, evt) {
+
+ // evt.data = elementView.model.position();
+ // },
+ 'element:pointerup': function(elementView, evt, x, y) {
+ var coordinates = new g.Point(x, y);
+ var elementAbove = elementView.model;
+ var elementBelow = this.model.findModelsFromPoint(coordinates).find(function(el) {
+ return (el.id !== elementAbove.id);
+ });
+ if(elementBelow) elementBelow.embed(elementAbove);
+ }
+
+ }); //end of my event
+ }
+
+ createCustomElement() {
+ joint.shapes.html = {};
+ joint.shapes.html.Element = joint.shapes.basic.Rect.extend({
+ defaults: joint.util.deepSupplement({
+ type: 'html.Element',
+ attrs: {
+ rect: { stroke: 'none', 'fill-opacity': 0 }
+ }
+ }, joint.shapes.basic.Rect.prototype.defaults)
+ });
+
+ // / Create a custom view for that element that displays an HTML div above it.
+ // -------------------------------------------------------------------------
+
+ joint.shapes.html.ElementView = joint.dia.ElementView.extend({
+
+ template: [
+ '<div class="html-element">',
+ '<button class="delete">x</button>',
+ '<label></label>',
+ '<span></span>', '<br/>',
+ '<select><option>--</option><option>one</option><option>two</option></select>',
+ '<input type="text" value="I\'m HTML input" />',
+ '</div>'
+ ].join(''),
+
+ initialize: function() {
+ _.bindAll(this, 'updateBox');
+ joint.dia.ElementView.prototype.initialize.apply(this, arguments);
+
+ this.$box = $(_.template(this.template)());
+ // Prevent paper from handling pointerdown.
+ this.$box.find('input,select').on('mousedown click', function(evt) {
+ evt.stopPropagation();
+ });
+ // This is an example of reacting on the input change and storing the input data in the cell model.
+ this.$box.find('input').on('change', _.bind(function(evt) {
+ this.model.set('input', $(evt.target).val());
+ }, this));
+ this.$box.find('select').on('change', _.bind(function(evt) {
+ this.model.set('select', $(evt.target).val());
+ }, this));
+ this.$box.find('select').val(this.model.get('select'));
+ this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model));
+ // Update the box position whenever the underlying model changes.
+ this.model.on('change', this.updateBox, this);
+ // Remove the box when the model gets removed from the graph.
+ this.model.on('remove', this.removeBox, this);
+
+ this.updateBox();
+ },
+
+ render: function() {
+ joint.dia.ElementView.prototype.render.apply(this, arguments);
+ this.paper.$el.prepend(this.$box);
+ this.updateBox();
+ return this;
+ },
+
+ updateBox: function() {
+ // Set the position and dimension of the box so that it covers the JointJS element.
+ var bbox = this.model.getBBox();
+ // Example of updating the HTML with a data stored in the cell model.
+ this.$box.find('label').text(this.model.get('label'));
+ this.$box.find('span').text(this.model.get('select'));
+ this.$box.css({
+ width: bbox.width,
+ height: bbox.height,
+ left: bbox.x,
+ top: bbox.y,
+ transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)'
+ });
+ },
+
+ removeBox: function(evt) {
+ this.$box.remove();
+ }
+ });
+
+ // Create JointJS elements and add them to the graph as usual.
+ // -----------------------------------------------------------
+
+ var el1 = new joint.shapes.html.Element({
+ position: { x: 10, y: 10 },
+ size: { width: 170, height: 100 },
+ label: 'I am HTML',
+ select: 'one'
+ });
+
+ var el2 = new joint.shapes.html.Element({
+ position: { x: 370, y: 160 },
+ size: { width: 170, height: 100 },
+ label: 'Me too',
+ select: 'two'
+ });
+ var l = new joint.dia.Link({
+ source: { id: el1.id },
+ target: { id: el2.id },
+ attrs: { '.connection': { 'stroke-width': 5, stroke: '#34495E' }}
+ });
+
+ let elementArray : any[] = [];
+ elementArray.push(el1, el2);
+ return elementArray;
+ }
+
+ myCustomElementGenerator() {
+ var Ellipse = joint.dia.Element.define('examples.Ellipse', {
+ // default attributes
+ markup: [{
+ tagName: 'ellipse',
+ selector: 'ellipse' // not necessary but faster
+ }],
+ attrs: {
+ ellipse: {
+ fill: 'white',
+ stroke: 'black',
+ strokeWidth: 4,
+ refRx: .5,
+ refRy: .5,
+ refCx: .5,
+ refCy: .5
+ }
+ }
+ });
+
+ var Rectangle = joint.shapes.standard.Rectangle.define('examples.CustomRectangle', {
+ markup: [{
+ tagName: 'body',
+ selector: 'body' // not necessary but faster
+ },
+ {
+ tagName: 'label',
+ selector: 'label'
+ }],
+ attrs: {
+ body: {
+ rx: 10, // add a corner radius
+ ry: 10,
+ strokeWidth: 1,
+ fill: 'cornflowerblue'
+ },
+ label: {
+ textAnchor: 'left', // align text to left
+ refX: 10, // offset text from right edge of model bbox
+ fill: 'white',
+ fontSize: 18,
+ text: 'mad mad mad'
+ }
+ }
+ })
+
+
+ var customElement = (new joint.dia.Element.examples.Ellipse()).position(100, 100).size(120, 50);
+ let elementsArray = [];
+ elementsArray.push(customElement);
+
+ var customRect = new Rectangle().position(100, 200).size(120, 120);
+ elementsArray.push(customRect);
+ return elementsArray;
+ }
+
+ convertGraphToJson() {
+ this.grapJson = JSON.stringify(this.graph.toJSON());
+ // this.grapJson = this.graph.toJSON();
+ console.log(this.graph.toJSON());
+ console.log(this.grapJson);
+ this.sourceMode = true;
+ }
+
+ setNewValue(event) {
+ // this.selectedElement.attr('label/text', event.currentTarget.value);
+ }
+
+ convertJsonToGraph() {
+ this.sourceMode = false;
+ }
+
+ zoomIn() {
+ var graphScale = 1;
+ graphScale += 0.1;
+ this.paper.scale(graphScale, graphScale);
+ }
+
+ zoomOut() {
+ var graphScale = 1;
+ graphScale -= 0.1;
+ this.paper.scale(graphScale, graphScale);
+ }
+
+ createContainerElements() {
+ this.graph = new joint.dia.Graph;
+
+ this.paper = new joint.dia.Paper({
+
+ el: document.getElementById('paper'),
+ width: 800,
+ height: 400,
+ gridSize: 1,
+ model: this.graph,
+ snapLinks: true,
+ linkPinning: false,
+ embeddingMode: true,
+ clickThreshold: 5,
+ defaultConnectionPoint: { name: 'boundary' },
+ highlighting: {
+ 'default': {
+ name: 'stroke',
+ options: {
+ padding: 6
+ }
+ },
+ 'embedding': {
+ name: 'addClass',
+ options: {
+ className: 'highlighted-parent'
+ }
+ }
+ },
+
+ validateEmbedding: function(childView, parentView) {
+ return parentView.model instanceof joint.shapes.devs.Coupled;
+ },
+
+ validateConnection: function(sourceView, sourceMagnet, targetView, targetMagnet) {
+ return sourceMagnet != targetMagnet;
+ }
+ });
+
+ let c1 = new joint.shapes.devs.Coupled({
+ position: {
+ x: 230,
+ y: 50
+ },
+ size: {
+ width: 300,
+ height: 300
+ }
+});
+
+c1.set('inPorts', ['in']);
+c1.set('outPorts', ['out 1', 'out 2']);
+
+var a1 = new joint.shapes.devs.Atomic({
+ position: {
+ x: 360,
+ y: 260
+ },
+ inPorts: ['xy'],
+ outPorts: ['x', 'y']
+});
+
+var a2 = new joint.shapes.devs.Atomic({
+ position: {
+ x: 50,
+ y: 160
+ },
+ outPorts: ['out']
+});
+
+var a3 = new joint.shapes.devs.Atomic({
+ position: {
+ x: 650,
+ y: 50
+ },
+ size: {
+ width: 100,
+ height: 300
+ },
+ inPorts: ['a', 'b']
+});
+
+[c1, a1, a2, a3].forEach(function(element) {
+ element.attr({
+ '.body': {
+ 'rx': 6,
+ 'ry': 6
+ }
+ });
+});
+
+
+
+this.graph.addCells([c1, a1, a2, a3]);
+
+c1.embed(a1);
+
+this.connect(a2, 'out', c1, 'in');
+this.connect(c1, 'in', a1, 'xy');
+this.connect(a1, 'x', c1, 'out 1');
+this.connect(a1, 'y', c1, 'out 2');
+this.connect(c1, 'out 1', a3, 'a');
+this.connect(c1, 'out 2', a3, 'b');
+
+var strokeDasharrayPath = '.body/strokeDasharray';
+let _this = this;
+
+this.paper.on('element:pointerdblclick', function(elementView) {
+ var element = elementView.model;
+ if (element.get('type') === 'devs.Atomic') {
+ _this.toggleDelegation(element);
+ }
+});
+
+this.paper.setInteractivity(function(elementView) {
+ return {
+ stopDelegation: !elementView.model.attr(strokeDasharrayPath)
+ };
+});
+
+
+} // function end
+
+ // function
+ connect(source, sourcePort, target, targetPort) {
+
+ var link = new joint.shapes.devs.Link({
+ source: {
+ id: source.id,
+ port: sourcePort
+ },
+ target: {
+ id: target.id,
+ port: targetPort
+ }
+ });
+
+ link.addTo(this.graph).reparent();
+ }
+
+ toggleDelegation(element) {
+ var strokeDasharrayPath = '.body/strokeDasharray';
+ element.attr(strokeDasharrayPath, element.attr(strokeDasharrayPath) ? '' : '15,1');
+}
+
+createContainerElemnetsByDragDrop() {
+
+
+}
+}
diff --git a/cds-ui/client/JointJS-POC-In-Progress/app.module.ts b/cds-ui/client/JointJS-POC-In-Progress/app.module.ts
new file mode 100644
index 000000000..15eb6d5fc
--- /dev/null
+++ b/cds-ui/client/JointJS-POC-In-Progress/app.module.ts
@@ -0,0 +1,24 @@
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { CommonModule } from '@angular/common';
+
+import { AppRoutingModule } from './app-routing.module';
+import { AppComponent } from './app.component';
+import { DragCopyComponent } from './drag-copy/drag-copy.component';
+
+@NgModule({
+ declarations: [
+ AppComponent,
+ DragCopyComponent
+ ],
+ imports: [
+ BrowserModule,
+ AppRoutingModule,
+ FormsModule,
+ CommonModule
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+})
+export class AppModule { }