From 9a028134c4b528d891b4921a686468390d1a8327 Mon Sep 17 00:00:00 2001 From: Arthur Khokhlov Date: Wed, 15 Jun 2022 19:53:00 +0300 Subject: [PATCH 1/5] material-tree --- angular.json | 2 + package.json | 2 + src/app/app-routing.module.ts | 5 +- src/app/app.component.html | 2 +- src/app/app.component.scss | 11 +- src/app/app.component.spec.ts | 6 - src/app/app.component.ts | 42 ----- src/app/app.module.ts | 6 +- src/app/tree/hyperlink-highlighter.ts | 32 ++++ src/app/tree/tabs-data.service.spec.ts | 16 ++ .../tree-container.component.html | 26 +++ .../tree-container.component.scss | 56 ++++++ .../tree-container.component.spec.ts | 25 +++ .../tree-container.component.ts | 143 ++++++++++++++++ src/app/tree/tree-data.service.ts | 162 ++++++++++++++++++ src/app/tree/tree-routing.module.ts | 13 ++ src/app/tree/tree.models.ts | 10 ++ src/app/tree/tree.module.ts | 21 +++ src/index.html | 5 +- src/styles.scss | 41 ++++- 20 files changed, 564 insertions(+), 62 deletions(-) create mode 100644 src/app/tree/hyperlink-highlighter.ts create mode 100644 src/app/tree/tabs-data.service.spec.ts create mode 100644 src/app/tree/tree-container/tree-container.component.html create mode 100644 src/app/tree/tree-container/tree-container.component.scss create mode 100644 src/app/tree/tree-container/tree-container.component.spec.ts create mode 100644 src/app/tree/tree-container/tree-container.component.ts create mode 100644 src/app/tree/tree-data.service.ts create mode 100644 src/app/tree/tree-routing.module.ts create mode 100644 src/app/tree/tree.models.ts create mode 100644 src/app/tree/tree.module.ts diff --git a/angular.json b/angular.json index 0ddaf1e..b1c0fe1 100644 --- a/angular.json +++ b/angular.json @@ -31,6 +31,7 @@ "src/assets" ], "styles": [ + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.scss" ], "scripts": [] @@ -99,6 +100,7 @@ "src/assets" ], "styles": [ + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.scss" ], "scripts": [] diff --git a/package.json b/package.json index b7f6fab..8382c10 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,12 @@ "private": true, "dependencies": { "@angular/animations": "~12.0.5", + "@angular/cdk": "^12.2.13", "@angular/common": "~12.0.5", "@angular/compiler": "~12.0.5", "@angular/core": "~12.0.5", "@angular/forms": "~12.0.5", + "@angular/material": "^12.2.13", "@angular/platform-browser": "~12.0.5", "@angular/platform-browser-dynamic": "~12.0.5", "@angular/router": "~12.0.5", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 0297262..d6d936f 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,7 +1,10 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -const routes: Routes = []; +const routes: Routes = [ + { path: '', redirectTo: '/tree-container', pathMatch: 'full' }, + { path: '**', redirectTo: '/tree-container', pathMatch: 'full' } +]; @NgModule({ imports: [RouterModule.forRoot(routes)], diff --git a/src/app/app.component.html b/src/app/app.component.html index 173df6a..0680b43 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1 +1 @@ -
+ diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 6fae84a..39e7f4e 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,8 +1,5 @@ -.canvas { - width: 100%; +:host { + box-sizing: border-box; + display: block; height: 100%; - - .joint-paper { - border: 1px solid #A0A0A0; - } -} +} \ No newline at end of file diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 10497da..7794a50 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -20,12 +20,6 @@ describe('AppComponent', () => { expect(app).toBeTruthy(); }); - it(`should have as title 'rappid-angular'`, () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app.title).toEqual('rappid-angular'); - }); - it('should render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 3d7d5be..2d8b367 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,5 +1,4 @@ import { AfterViewInit, OnInit, Component, ElementRef, ViewChild } from '@angular/core'; -import { dia, ui, shapes } from '@clientio/rappid'; @Component({ selector: 'app-root', @@ -7,50 +6,9 @@ import { dia, ui, shapes } from '@clientio/rappid'; styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit, AfterViewInit { - @ViewChild('canvas') canvas: ElementRef; - - private graph: dia.Graph; - private paper: dia.Paper; - private scroller: ui.PaperScroller; - public ngOnInit(): void { - const graph = this.graph = new dia.Graph({}, { cellNamespace: shapes }); - - const paper = this.paper = new dia.Paper({ - model: graph, - background: { - color: '#F8F9FA', - }, - frozen: true, - async: true, - cellViewNamespace: shapes - }); - - const scroller = this.scroller = new ui.PaperScroller({ - paper, - autoResizePaper: true, - cursor: 'grab' - }); - - scroller.render(); - - const rect = new shapes.standard.Rectangle({ - position: { x: 100, y: 100 }, - size: { width: 100, height: 50 }, - attrs: { - label: { - text: 'Hello World' - } - } - }); - - this.graph.addCell(rect); } public ngAfterViewInit(): void { - const { scroller, paper, canvas } = this; - canvas.nativeElement.appendChild(this.scroller.el); - scroller.center(); - paper.unfreeze(); } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b1c6c96..a219c20 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -3,6 +3,8 @@ import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { TreeModule } from './tree/tree.module'; @NgModule({ declarations: [ @@ -10,7 +12,9 @@ import { AppComponent } from './app.component'; ], imports: [ BrowserModule, - AppRoutingModule + AppRoutingModule, + BrowserAnimationsModule, + TreeModule ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/tree/hyperlink-highlighter.ts b/src/app/tree/hyperlink-highlighter.ts new file mode 100644 index 0000000..6b4d476 --- /dev/null +++ b/src/app/tree/hyperlink-highlighter.ts @@ -0,0 +1,32 @@ +import { dia } from '@clientio/rappid'; + +interface HyperlinkHighlighterOptions extends dia.HighlighterView.Options { + path: string; +} + +export class HyperlinkHighlighter extends dia.HighlighterView { + + highlight(elementView: dia.ElementView, node: SVGElement) { + const { path } = this.options; + const hyperlink = elementView.model.prop(path); + if (!hyperlink) return; + node.style.textDecoration = 'underline'; + node.style.fill = '#0099ff'; + node.style.cursor = 'pointer'; + node.setAttribute('event', 'element:link'); + node.dataset.tooltip = 'Click to open the sub-process.'; + node.dataset.hyperlink = hyperlink; + } + + static addToLabel(element: dia.Element, paper: dia.Paper, path: string) { + return this.add( + element.findView(paper), + // The element selector pointing to the SVGText sub-element + 'label', + // The unique ID of the highlighter + 'hyperlink-highlighter', + // Options + { path } + ); + } + } \ No newline at end of file diff --git a/src/app/tree/tabs-data.service.spec.ts b/src/app/tree/tabs-data.service.spec.ts new file mode 100644 index 0000000..26f4279 --- /dev/null +++ b/src/app/tree/tabs-data.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { TreeDataService } from './tree-data.service'; + +describe('TabsDataService', () => { + let service: TreeDataService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(TreeDataService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/tree/tree-container/tree-container.component.html b/src/app/tree/tree-container/tree-container.component.html new file mode 100644 index 0000000..cbb497e --- /dev/null +++ b/src/app/tree/tree-container/tree-container.component.html @@ -0,0 +1,26 @@ +
+ + + + + {{ (node.isElement ? '▱ ' : '⇢ ') + node.name}} + + + +
+ + {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}} + + {{node.name}} +
+ +
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/src/app/tree/tree-container/tree-container.component.scss b/src/app/tree/tree-container/tree-container.component.scss new file mode 100644 index 0000000..4ef7903 --- /dev/null +++ b/src/app/tree/tree-container/tree-container.component.scss @@ -0,0 +1,56 @@ +:host { + height: 100%; + display: flex; + flex-direction: row; +} + +.tree-invisible { + display: none; +} + +.tree ul, +.tree li { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + + +/* + * This padding sets alignment of the nested nodes. + */ + +.tree .mat-nested-tree-node div[role=group] { + padding-left: 20px; + background-color: #f5f5f5; +} + + +/* + * Padding for leaf nodes. + * Leaf nodes need to have padding so as to align with other non-leaf nodes + * under the same parent. + */ + +.tree div[role=group]>.mat-tree-node { + padding-left: 10px +} + +.tree .mat-tree-node { + cursor: pointer; + user-select: none; + background-color: #f5f5f5; +} + +.tree .mat-tree-node.selected { + background: #08b081; + color: #fff; +} + +.tree-container { + min-width: 200px; + width: 25%; + height: 100vh; + border-right: 1px solid #e2e2e2; + background-color: #f5f5f5; +} \ No newline at end of file diff --git a/src/app/tree/tree-container/tree-container.component.spec.ts b/src/app/tree/tree-container/tree-container.component.spec.ts new file mode 100644 index 0000000..59b2bf8 --- /dev/null +++ b/src/app/tree/tree-container/tree-container.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TreeContainerComponent } from './tree-container.component'; + +describe('TabsContainerComponent', () => { + let component: TreeContainerComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TreeContainerComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TreeContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/tree/tree-container/tree-container.component.ts b/src/app/tree/tree-container/tree-container.component.ts new file mode 100644 index 0000000..061a47c --- /dev/null +++ b/src/app/tree/tree-container/tree-container.component.ts @@ -0,0 +1,143 @@ +import { NestedTreeControl } from '@angular/cdk/tree'; +import { AfterViewInit, Component, OnInit, QueryList, ViewChild, ViewChildren, ElementRef } from '@angular/core'; +import { MatTabChangeEvent, MatTabGroup } from '@angular/material/tabs'; +import { MatTreeNestedDataSource } from '@angular/material/tree'; +import { dia, highlighters, shapes, ui } from '@clientio/rappid'; +import { TreeDataService } from '../tree-data.service'; +import { TreeNode } from '../tree.models'; + +@Component({ + selector: 'app-tree-container', + templateUrl: './tree-container.component.html', + styleUrls: ['./tree-container.component.scss'] +}) +export class TreeContainerComponent implements OnInit, AfterViewInit { + trees: TreeNode[]; + nodes: { [key: string]: TreeNode } = {}; + treeControl = new NestedTreeControl(node => node.children); + dataSource = new MatTreeNestedDataSource(); + selectedNode: TreeNode; + graph: dia.Graph; + paper: dia.Paper; + @ViewChild('canvas') canvas: ElementRef; + + constructor(private treeDataService: TreeDataService) { + this.trees = this.treeDataService.getTree(); + this.dataSource.data = this.trees; + this.trees.forEach(node => { + this.nodes[node.id] = node; + if (node.children) { + node.children.forEach(node => { + this.nodes[node.id] = node; + }); + } + }); + + this.selectedNode = this.trees[0]; + this.selectedNode.selected = true; + this.treeControl.toggle(this.selectedNode); + this.graph = new dia.Graph({}, { cellNamespace: shapes }); + this.graph.fromJSON(this.trees[0].graph); + } + + ngOnInit(): void { + } + + ngAfterViewInit(): void { + this.paper = new dia.Paper({ + model: this.graph, + async: true, + frozen: true, + cellViewNamespace: shapes, + clickThreshold: 10, + moveThreshold: 10, + interactive: false, + defaultConnectionPoint: { + name: 'boundary' + } + }); + + const scroller = new ui.PaperScroller({ + paper: this.paper, + autoResizePaper: true, + cursor: 'grab', + baseWidth: 1, + baseHeight: 1, + padding: 0, + contentOptions: { + useModelGeometry: true, + padding: 200 + } + }); + + this.canvas.nativeElement.appendChild(scroller.el); + scroller.render().centerContent({ useModelGeometry: true }); + this.paper.unfreeze(); + + this.paper.on('cell:pointerclick', (cellView) => { + const cell = cellView.model; + const nodeId = `${this.graph.id}-${cell.id}`; + this.graph.set('selectedCell', cell.id); + this.treeControl.expand(this.nodes[this.graph.id]); + this.selectTreeNode(this.nodes[nodeId]); + }); + + this.paper.on('blank:pointerclick', () => { + this.graph.set('selectedCell', null); + this.selectTreeNode(this.nodes[this.graph.id]); + (document.activeElement as HTMLElement)?.blur(); + }); + + this.paper.on('blank:pointerdown', (evt) => scroller.startPanning(evt)); + + let selectionFrame: highlighters.mask | null = null; + + this.paper.listenTo(this.graph, 'change:selectedCell', () => { + if (selectionFrame) { + selectionFrame.remove(); + selectionFrame = null; + } + const cellId = this.graph.get('selectedCell'); + const cell = this.graph.getCell(cellId); + if (cell) { + selectionFrame = highlighters.mask.add( + cell.findView(this.paper), + cell.isLink() ? 'line' : 'body', + 'selection-frame', + { + layer: dia.Paper.Layers.BACK, + padding: 4, + attrs: { + 'stroke-width': 2, + 'stroke-linecap': 'round', + 'opacity': '0.6' + } + } + ); + } + }); + } + + hasChild = (_: number, node: TreeNode) => !!node.children && node.children.length > 0; + + selectTreeNode(node: TreeNode) { + if (this.selectedNode && this.selectedNode.id !== node.id) { + this.selectedNode.selected = false; + } + const graphId = node.id.split('-')[0]; + const cellId = node.id.split('-')[1]; + if (graphId !== this.graph.id) { + this.graph.fromJSON(this.nodes[graphId].graph); + } + if (cellId) { + this.graph.set('selectedCell', cellId); + } + this.selectedNode = node; + this.selectedNode.selected = true; + } + + onNodeClick(node: TreeNode) { + this.treeControl.toggle(node); + this.selectTreeNode(node); + } +} diff --git a/src/app/tree/tree-data.service.ts b/src/app/tree/tree-data.service.ts new file mode 100644 index 0000000..a27c055 --- /dev/null +++ b/src/app/tree/tree-data.service.ts @@ -0,0 +1,162 @@ +import { Injectable } from '@angular/core'; +import { TreeNode } from './tree.models'; +import { dia, shapes } from '@clientio/rappid'; + +const data: any[] = [ + { + id: 'process0', + name: 'Process 1', + cells: [{ + id: 'r3', + type: 'standard.Rectangle', + position: { x: 200, y: 80 }, + size: { width: 100, height: 60 }, + attrs: { + body: { + rx: 20, + ry: 20, + }, + label: { + text: 'Start' + } + } + }, { + id: 'p2', + type: 'standard.Path', + position: { x: 200, y: 230 }, + size: { width: 100, height: 60 }, + attrs: { + body: { + d: 'M 20 0 H calc(w) L calc(w-20) calc(h) H 0 Z' + }, + label: { + text: 'Input' + } + } + }, { + id: 'p1', + type: 'standard.Path', + position: { x: 200, y: 400 }, + size: { width: 100, height: 100 }, + attrs: { + body: { + d: 'M 0 calc(0.5 * h) calc(0.5 * w) 0 calc(w) calc(0.5 * h) calc(0.5 * w) calc(h) Z' + }, + label: { + text: 'Decision' + } + } + }, { + id: 'r4', + type: 'standard.Rectangle', + position: { x: 200, y: 600 }, + size: { width: 100, height: 60 }, + attrs: { + label: { + text: 'Process' + } + } + }, { + id: 'e1', + type: 'standard.Ellipse', + position: { x: 220, y: 750 }, + size: { width: 60, height: 60 }, + attrs: { + label: { + text: 'End' + } + } + }, { + id: 'l1', + type: 'standard.Link', + source: { id: 'r3' }, + target: { id: 'p2' } + }, { + id: 'l2', + type: 'standard.Link', + source: { id: 'p2' }, + target: { id: 'p1' } + }, { + id: 'l3', + type: 'standard.Link', + source: { id: 'p1' }, + target: { id: 'r4' }, + labels: [{ attrs: { text: { text: 'Yes' } } }] + }, { + id: 'l4', + type: 'standard.Link', + source: { id: 'p1' }, + target: { id: 'p2' }, + vertices: [{ x: 400, y: 450 }, { x: 400, y: 260 }], + labels: [{ attrs: { text: { text: 'No' } } }] + }, { + id: 'l5', + type: 'standard.Link', + source: { id: 'r4' }, + target: { id: 'e1' } + }] + }, { + id: 'process1', + name: 'Process 2', + cells: [{ + id: 'r1', + type: 'standard.Rectangle', + position: { x: 100, y: 100 }, + size: { width: 100, height: 100 }, + attrs: { + label: { + text: 'Source' + } + } + }, { + id: 'r2', + type: 'standard.Rectangle', + position: { x: 300, y: 100 }, + size: { width: 100, height: 100 }, + attrs: { + label: { + text: 'Target' + } + } + }, { + id: 'l6', + type: 'standard.Link', + source: { id: 'r1', anchor: { name: 'center', args: { dy: -10 } } }, + target: { id: 'r2', anchor: { name: 'center', args: { dy: -10 } } }, + }, { + id: 'l7', + type: 'standard.Link', + source: { id: 'r1', anchor: { name: 'center', args: { dy: 10 } } }, + target: { id: 'r2', anchor: { name: 'center', args: { dy: 10 } } } + }], + } +]; + +@Injectable({ + providedIn: 'root' +}) +export class TreeDataService { + + constructor() { } + + getTree(): TreeNode[] { + return data.map(diagram => { + const graph = new dia.Graph({}, { cellNamespace: shapes }); + graph.fromJSON(diagram); + return { + id: diagram.id, + name: diagram.name, + graph: diagram, + children: graph.getCells().map((cell: any) => { + return { + id: `${diagram.id}-${cell.id}`, + name: cell.isElement() + ? cell.attr(['label', 'text']) || `Element (${cell.id})` + : cell.prop(['labels', 0, 'attrs', 'text', 'text']) || `Link (${cell.id})`, + isElement: cell.isElement(), + } + }) + } + }); + } +} diff --git a/src/app/tree/tree-routing.module.ts b/src/app/tree/tree-routing.module.ts new file mode 100644 index 0000000..360f593 --- /dev/null +++ b/src/app/tree/tree-routing.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { TreeContainerComponent } from './tree-container/tree-container.component'; + +const routes: Routes = [ + { path: 'tree-container', component: TreeContainerComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class TreeRoutingModule { } diff --git a/src/app/tree/tree.models.ts b/src/app/tree/tree.models.ts new file mode 100644 index 0000000..c7fe21f --- /dev/null +++ b/src/app/tree/tree.models.ts @@ -0,0 +1,10 @@ +import { dia } from "@clientio/rappid"; + +export interface TreeNode { + id: string, + name: string, + graph?: dia.Graph, + children?: TreeNode[], + isElement?: boolean, + selected?: boolean +} \ No newline at end of file diff --git a/src/app/tree/tree.module.ts b/src/app/tree/tree.module.ts new file mode 100644 index 0000000..5911b48 --- /dev/null +++ b/src/app/tree/tree.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { MatTreeModule } from '@angular/material/tree'; +import { MatIconModule } from '@angular/material/icon'; +import { MatButtonModule } from '@angular/material/button'; +import { TreeRoutingModule } from './tree-routing.module'; +import { TreeContainerComponent } from './tree-container/tree-container.component'; + +@NgModule({ + declarations: [ + TreeContainerComponent + ], + imports: [ + CommonModule, + TreeRoutingModule, + MatTreeModule, + MatIconModule, + MatButtonModule + ] +}) +export class TreeModule { } diff --git a/src/index.html b/src/index.html index aa9ae40..0269573 100644 --- a/src/index.html +++ b/src/index.html @@ -6,8 +6,11 @@ + + + - + diff --git a/src/styles.scss b/src/styles.scss index 1737b82..79352f2 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,8 +1,43 @@ /* You can add global styles to this file, and also import other style files */ + @import "~@clientio/rappid/rappid.css"; +body { + height: 100vh; + box-sizing: border-box; + margin: 0; +} +html, body { - height: 100vh; - box-sizing: border-box; - margin: 0; + height: 100%; } + +body { + margin: 0; + font-family: Roboto, "Helvetica Neue", sans-serif; +} + +.mat-tab-group.mat-tab-fill-height .mat-tab-body-wrapper { + flex: 1 1 100%; +} + +.canvas { + width: 75%; + height: 100vh; + .joint-paper { + .joint-highlight-mask { + fill: #08B081; + } + // Arrowheads + marker path { + stroke: #08B081; + fill: #08B081; + } + .joint-link [joint-selector="line"], + .joint-element ellipse, + .joint-element path, + .joint-element rect { + stroke: #08B081; + } + } +} \ No newline at end of file From 37e7709d3d70e078805684694ae1c6b735892a72 Mon Sep 17 00:00:00 2001 From: Arthur Khokhlov Date: Wed, 15 Jun 2022 20:15:03 +0300 Subject: [PATCH 2/5] update --- src/app/app.component.ts | 2 +- src/app/tree/hyperlink-highlighter.ts | 32 ------------------- .../tree-container.component.ts | 6 ++-- 3 files changed, 3 insertions(+), 37 deletions(-) delete mode 100644 src/app/tree/hyperlink-highlighter.ts diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2d8b367..164621c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, OnInit, Component, ElementRef, ViewChild } from '@angular/core'; +import { AfterViewInit, OnInit, Component } from '@angular/core'; @Component({ selector: 'app-root', diff --git a/src/app/tree/hyperlink-highlighter.ts b/src/app/tree/hyperlink-highlighter.ts deleted file mode 100644 index 6b4d476..0000000 --- a/src/app/tree/hyperlink-highlighter.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { dia } from '@clientio/rappid'; - -interface HyperlinkHighlighterOptions extends dia.HighlighterView.Options { - path: string; -} - -export class HyperlinkHighlighter extends dia.HighlighterView { - - highlight(elementView: dia.ElementView, node: SVGElement) { - const { path } = this.options; - const hyperlink = elementView.model.prop(path); - if (!hyperlink) return; - node.style.textDecoration = 'underline'; - node.style.fill = '#0099ff'; - node.style.cursor = 'pointer'; - node.setAttribute('event', 'element:link'); - node.dataset.tooltip = 'Click to open the sub-process.'; - node.dataset.hyperlink = hyperlink; - } - - static addToLabel(element: dia.Element, paper: dia.Paper, path: string) { - return this.add( - element.findView(paper), - // The element selector pointing to the SVGText sub-element - 'label', - // The unique ID of the highlighter - 'hyperlink-highlighter', - // Options - { path } - ); - } - } \ No newline at end of file diff --git a/src/app/tree/tree-container/tree-container.component.ts b/src/app/tree/tree-container/tree-container.component.ts index 061a47c..4637d44 100644 --- a/src/app/tree/tree-container/tree-container.component.ts +++ b/src/app/tree/tree-container/tree-container.component.ts @@ -1,6 +1,5 @@ import { NestedTreeControl } from '@angular/cdk/tree'; -import { AfterViewInit, Component, OnInit, QueryList, ViewChild, ViewChildren, ElementRef } from '@angular/core'; -import { MatTabChangeEvent, MatTabGroup } from '@angular/material/tabs'; +import { AfterViewInit, Component, OnInit, ViewChild, ElementRef } from '@angular/core'; import { MatTreeNestedDataSource } from '@angular/material/tree'; import { dia, highlighters, shapes, ui } from '@clientio/rappid'; import { TreeDataService } from '../tree-data.service'; @@ -124,8 +123,7 @@ export class TreeContainerComponent implements OnInit, AfterViewInit { if (this.selectedNode && this.selectedNode.id !== node.id) { this.selectedNode.selected = false; } - const graphId = node.id.split('-')[0]; - const cellId = node.id.split('-')[1]; + const [ graphId, cellId ] = node.id.split('-'); if (graphId !== this.graph.id) { this.graph.fromJSON(this.nodes[graphId].graph); } From e5de9753479843ffd53eb887536cf21ecf393766 Mon Sep 17 00:00:00 2001 From: Arthur Khokhlov Date: Tue, 21 Jun 2022 20:19:50 +0200 Subject: [PATCH 3/5] update to v14 --- .gitignore | 1 + angular.json | 4 +++- package.json | 28 ++++++++++++++-------------- tsconfig.json | 2 +- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 311ad7a..ccd5c88 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /dist /tmp /out-tsc +/.angular # Only exists if Bazel was run /bazel-out diff --git a/angular.json b/angular.json index b1c0fe1..9bef4a4 100644 --- a/angular.json +++ b/angular.json @@ -109,5 +109,7 @@ } } }, - "defaultProject": "rappid-angular" + "cli": { + "analytics": false + } } diff --git a/package.json b/package.json index 8382c10..d4ab086 100644 --- a/package.json +++ b/package.json @@ -10,25 +10,25 @@ }, "private": true, "dependencies": { - "@angular/animations": "~12.0.5", - "@angular/cdk": "^12.2.13", - "@angular/common": "~12.0.5", - "@angular/compiler": "~12.0.5", - "@angular/core": "~12.0.5", - "@angular/forms": "~12.0.5", - "@angular/material": "^12.2.13", - "@angular/platform-browser": "~12.0.5", - "@angular/platform-browser-dynamic": "~12.0.5", - "@angular/router": "~12.0.5", + "@angular/animations": "^14.0.2", + "@angular/cdk": "^14.0.2", + "@angular/common": "^14.0.2", + "@angular/compiler": "^14.0.2", + "@angular/core": "^14.0.2", + "@angular/forms": "^14.0.2", + "@angular/material": "^14.0.2", + "@angular/platform-browser": "^14.0.2", + "@angular/platform-browser-dynamic": "^14.0.2", + "@angular/router": "^14.0.2", "@clientio/rappid": "file:rappid.tgz", "rxjs": "~6.6.0", "tslib": "^2.1.0", "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "~12.0.5", - "@angular/cli": "~12.0.5", - "@angular/compiler-cli": "~12.0.5", + "@angular-devkit/build-angular": "^14.0.2", + "@angular/cli": "^14.0.2", + "@angular/compiler-cli": "^14.0.2", "@types/jasmine": "~3.6.0", "@types/node": "^12.11.1", "@types/backbone": "latest", @@ -39,6 +39,6 @@ "karma-coverage": "~2.0.3", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", - "typescript": "~4.2.3" + "typescript": "~4.6.4" } } diff --git a/tsconfig.json b/tsconfig.json index 3d8d984..7835a2b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,7 @@ "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, - "target": "es2017", + "target": "es2020", "module": "es2020", "lib": [ "es2018", From 159f19fd9de35aedeec3da36affa1c7c2be734ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kan=C4=9Bra?= <50818204+MartinKanera@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:09:32 +0100 Subject: [PATCH 4/5] chore: update imports to joint-plus signature (#8) --- .gitignore | 4 ++-- README.md | 4 ++-- package.json | 2 +- src/app/tree/tree-container/tree-container.component.ts | 2 +- src/app/tree/tree-data.service.ts | 2 +- src/app/tree/tree.models.ts | 4 ++-- src/styles.scss | 4 ++-- tsconfig.app.json | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index ccd5c88..4a2d2cb 100644 --- a/.gitignore +++ b/.gitignore @@ -46,5 +46,5 @@ testem.log .DS_Store Thumbs.db -# rappid -rappid.tgz +# joint-plus +joint-plus.tgz diff --git a/README.md b/README.md index aa98dd1..8db7155 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This git repository is intended for instructional purposes. It is the source cod ### Prerequisites -To run the following code, you will need a [Rappid license](https://www.jointjs.com/license) that comes with the Rappid installable package file `rappid.tgz`. +To run the following code, you will need a [Rappid license](https://www.jointjs.com/license) that comes with the Rappid installable package file `joint-plus.tgz`. ### Dependencies @@ -27,7 +27,7 @@ Change into the `rappid-tutorial-angular12` directory. cd rappid-tutorial-angular12 ``` -For this tutorial, you need to place your own `rappid.tgz` file in the root directory. +For this tutorial, you need to place your own `joint-plus.tgz` file in the root directory. When that is completed, you can install the dependencies. diff --git a/package.json b/package.json index d4ab086..47bb533 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@angular/platform-browser": "^14.0.2", "@angular/platform-browser-dynamic": "^14.0.2", "@angular/router": "^14.0.2", - "@clientio/rappid": "file:rappid.tgz", + "@joint/plus": "file:joint-plus.tgz", "rxjs": "~6.6.0", "tslib": "^2.1.0", "zone.js": "~0.11.4" diff --git a/src/app/tree/tree-container/tree-container.component.ts b/src/app/tree/tree-container/tree-container.component.ts index 4637d44..e66119f 100644 --- a/src/app/tree/tree-container/tree-container.component.ts +++ b/src/app/tree/tree-container/tree-container.component.ts @@ -1,7 +1,7 @@ import { NestedTreeControl } from '@angular/cdk/tree'; import { AfterViewInit, Component, OnInit, ViewChild, ElementRef } from '@angular/core'; import { MatTreeNestedDataSource } from '@angular/material/tree'; -import { dia, highlighters, shapes, ui } from '@clientio/rappid'; +import { dia, highlighters, shapes, ui } from '@joint/plus'; import { TreeDataService } from '../tree-data.service'; import { TreeNode } from '../tree.models'; diff --git a/src/app/tree/tree-data.service.ts b/src/app/tree/tree-data.service.ts index a27c055..2199be1 100644 --- a/src/app/tree/tree-data.service.ts +++ b/src/app/tree/tree-data.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { TreeNode } from './tree.models'; -import { dia, shapes } from '@clientio/rappid'; +import { dia, shapes } from '@joint/plus'; const data: any[] = [ { diff --git a/src/app/tree/tree.models.ts b/src/app/tree/tree.models.ts index c7fe21f..fd2ffa6 100644 --- a/src/app/tree/tree.models.ts +++ b/src/app/tree/tree.models.ts @@ -1,4 +1,4 @@ -import { dia } from "@clientio/rappid"; +import { dia } from "@joint/plus"; export interface TreeNode { id: string, @@ -7,4 +7,4 @@ export interface TreeNode { children?: TreeNode[], isElement?: boolean, selected?: boolean -} \ No newline at end of file +} diff --git a/src/styles.scss b/src/styles.scss index 79352f2..15fced2 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,6 +1,6 @@ /* You can add global styles to this file, and also import other style files */ -@import "~@clientio/rappid/rappid.css"; +@import "~@joint/plus/joint-plus.css"; body { height: 100vh; box-sizing: border-box; @@ -40,4 +40,4 @@ body { stroke: #08B081; } } -} \ No newline at end of file +} diff --git a/tsconfig.app.json b/tsconfig.app.json index d1842cc..f756204 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -8,7 +8,7 @@ "files": [ "src/main.ts", "src/polyfills.ts", - "node_modules/@clientio/rappid/index.ts" + "node_modules/@joint/plus/index.ts" ], "include": [ "src/**/*.d.ts" From 8e4aab65d6152bdb8202f2ff740e9dca2abd4f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kan=C4=9Bra?= <50818204+MartinKanera@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:04:14 +0100 Subject: [PATCH 5/5] chore: remove types dependencies (#12) --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index 47bb533..a51487d 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,6 @@ "@angular/compiler-cli": "^14.0.2", "@types/jasmine": "~3.6.0", "@types/node": "^12.11.1", - "@types/backbone": "latest", - "@types/jquery": "latest", "jasmine-core": "~3.7.0", "karma": "~6.3.0", "karma-chrome-launcher": "~3.1.0",