feat: add graph framework
This commit is contained in:
parent
896b012c71
commit
93b7cd3959
225
frontend/package-lock.json
generated
225
frontend/package-lock.json
generated
@ -20,6 +20,7 @@
|
||||
"@angular/platform-browser-dynamic": "^18.1.0",
|
||||
"@angular/router": "^18.1.0",
|
||||
"@codemirror/lang-python": "^6.1.6",
|
||||
"@kr0san89/ngx-graph": "^11.0.0",
|
||||
"@xyflow/system": "^0.0.37",
|
||||
"codemirror": "^6.0.1",
|
||||
"codemirror-extension-inline-suggestion": "^0.0.3",
|
||||
@ -3957,6 +3958,35 @@
|
||||
"tslib": "2"
|
||||
}
|
||||
},
|
||||
"node_modules/@kr0san89/ngx-graph": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://npm.fnexe.com/@kr0san89/ngx-graph/-/ngx-graph-11.0.0.tgz",
|
||||
"integrity": "sha512-MMVxJ+ShZqnva7qerDk/M0xtyz4MzVoSsQRo0DH9DFvKtuG99SHhw9+vPtDJl8oomN04PACyzTufY/fCT63lZg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d3-color": "^3.1.0",
|
||||
"d3-dispatch": "^3.0.1",
|
||||
"d3-ease": "^3.0.1",
|
||||
"d3-force": "^3.0.0",
|
||||
"d3-interpolate": "3.0.1",
|
||||
"d3-scale": "4.0.2",
|
||||
"d3-selection": "^3.0.0",
|
||||
"d3-shape": "^3.2.0",
|
||||
"d3-timer": "^3.0.1",
|
||||
"d3-transition": "^3.0.1",
|
||||
"dagre": "^0.8.4",
|
||||
"transformation-matrix": "^1.15.3",
|
||||
"tslib": "^2.0.0",
|
||||
"webcola": "^3.3.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/animations": "18.x",
|
||||
"@angular/cdk": "18.x",
|
||||
"@angular/common": "18.x",
|
||||
"@angular/core": "18.x",
|
||||
"rxjs": "6.x || 7.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@leichtgewicht/ip-codec": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://npm.fnexe.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
|
||||
@ -8482,6 +8512,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/d3-array": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://npm.fnexe.com/d3-array/-/d3-array-3.2.4.tgz",
|
||||
"integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"internmap": "1 - 2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-color": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://npm.fnexe.com/d3-color/-/d3-color-3.1.0.tgz",
|
||||
@ -8522,6 +8564,29 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-force": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://npm.fnexe.com/d3-force/-/d3-force-3.0.0.tgz",
|
||||
"integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-dispatch": "1 - 3",
|
||||
"d3-quadtree": "1 - 3",
|
||||
"d3-timer": "1 - 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-format": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://npm.fnexe.com/d3-format/-/d3-format-3.1.0.tgz",
|
||||
"integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-interpolate": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://npm.fnexe.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
||||
@ -8534,6 +8599,40 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-path": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://npm.fnexe.com/d3-path/-/d3-path-3.1.0.tgz",
|
||||
"integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-quadtree": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://npm.fnexe.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
|
||||
"integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-scale": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://npm.fnexe.com/d3-scale/-/d3-scale-4.0.2.tgz",
|
||||
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-array": "2.10.0 - 3",
|
||||
"d3-format": "1 - 3",
|
||||
"d3-interpolate": "1.2.0 - 3",
|
||||
"d3-time": "2.1.1 - 3",
|
||||
"d3-time-format": "2 - 4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-selection": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://npm.fnexe.com/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||
@ -8543,6 +8642,42 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-shape": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://npm.fnexe.com/d3-shape/-/d3-shape-3.2.0.tgz",
|
||||
"integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-path": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-time": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://npm.fnexe.com/d3-time/-/d3-time-3.1.0.tgz",
|
||||
"integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-array": "2 - 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-time-format": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://npm.fnexe.com/d3-time-format/-/d3-time-format-4.1.0.tgz",
|
||||
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-time": "1 - 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-timer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://npm.fnexe.com/d3-timer/-/d3-timer-3.0.1.tgz",
|
||||
@ -8587,6 +8722,16 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/dagre": {
|
||||
"version": "0.8.5",
|
||||
"resolved": "https://npm.fnexe.com/dagre/-/dagre-0.8.5.tgz",
|
||||
"integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graphlib": "^2.1.8",
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"node_modules/date-format": {
|
||||
"version": "4.0.14",
|
||||
"resolved": "https://npm.fnexe.com/date-format/-/date-format-4.0.14.tgz",
|
||||
@ -10515,6 +10660,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/graphlib": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://npm.fnexe.com/graphlib/-/graphlib-2.1.8.tgz",
|
||||
"integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"node_modules/handle-thing": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://npm.fnexe.com/handle-thing/-/handle-thing-2.0.1.tgz",
|
||||
@ -11005,6 +11159,15 @@
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/internmap": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://npm.fnexe.com/internmap/-/internmap-2.0.3.tgz",
|
||||
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://npm.fnexe.com/ip-address/-/ip-address-9.0.5.tgz",
|
||||
@ -12396,7 +12559,6 @@
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://npm.fnexe.com/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
@ -16664,6 +16826,12 @@
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/transformation-matrix": {
|
||||
"version": "1.15.3",
|
||||
"resolved": "https://npm.fnexe.com/transformation-matrix/-/transformation-matrix-1.15.3.tgz",
|
||||
"integrity": "sha512-ThJH58GNFKhCw3gIoOtwf3tNwuYjbyEeiGdeq4mNMYWdJctnI896KUqn6PVt7jmNVepqa1bcKQtnMB1HtjsDMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tree-dump": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://npm.fnexe.com/tree-dump/-/tree-dump-1.0.2.tgz",
|
||||
@ -17191,6 +17359,61 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/webcola": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://npm.fnexe.com/webcola/-/webcola-3.4.0.tgz",
|
||||
"integrity": "sha512-4BiLXjXw3SJHo3Xd+rF+7fyClT6n7I+AR6TkBqyQ4kTsePSAMDLRCXY1f3B/kXJeP9tYn4G1TblxTO+jAt0gaw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d3-dispatch": "^1.0.3",
|
||||
"d3-drag": "^1.0.4",
|
||||
"d3-shape": "^1.3.5",
|
||||
"d3-timer": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/webcola/node_modules/d3-dispatch": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://npm.fnexe.com/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
|
||||
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/webcola/node_modules/d3-drag": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://npm.fnexe.com/d3-drag/-/d3-drag-1.2.5.tgz",
|
||||
"integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"d3-dispatch": "1",
|
||||
"d3-selection": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/webcola/node_modules/d3-path": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://npm.fnexe.com/d3-path/-/d3-path-1.0.9.tgz",
|
||||
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/webcola/node_modules/d3-selection": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://npm.fnexe.com/d3-selection/-/d3-selection-1.4.2.tgz",
|
||||
"integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/webcola/node_modules/d3-shape": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://npm.fnexe.com/d3-shape/-/d3-shape-1.3.7.tgz",
|
||||
"integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"d3-path": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/webcola/node_modules/d3-timer": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://npm.fnexe.com/d3-timer/-/d3-timer-1.0.10.tgz",
|
||||
"integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.92.1",
|
||||
"resolved": "https://npm.fnexe.com/webpack/-/webpack-5.92.1.tgz",
|
||||
|
@ -32,6 +32,7 @@
|
||||
"@angular/platform-browser-dynamic": "^18.1.0",
|
||||
"@angular/router": "^18.1.0",
|
||||
"@codemirror/lang-python": "^6.1.6",
|
||||
"@kr0san89/ngx-graph": "^11.0.0",
|
||||
"@xyflow/system": "^0.0.37",
|
||||
"codemirror": "^6.0.1",
|
||||
"codemirror-extension-inline-suggestion": "^0.0.3",
|
||||
|
@ -1,21 +1,122 @@
|
||||
<div>
|
||||
<h1>Slow shit</h1>
|
||||
<app-graph-component></app-graph-component>
|
||||
<div style="display: inline-block;position: relative">
|
||||
<div style="width: 500px;height: 300px;border:1px red solid; overflow: auto;" #parent (scroll)="handleMoved()">
|
||||
<div #source style="border:1px green solid;width: fit-content;margin-left:200px;margin-top:50px" cdkDrag (cdkDragMoved)="handleMoved()">
|
||||
I'm a div inside a SVG.
|
||||
</div>
|
||||
<div #target style="border:1px green solid;width: fit-content;margin-left:10px;margin-top:120px" cdkDrag (cdkDragMoved)="handleMoved()">
|
||||
I'm a second div inside a SVG.
|
||||
</div>
|
||||
<svg width="100%" height="100%" style="position: absolute;top:0px;left:0px;right:0;bottom:0;pointer-events: none;" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path #path stroke="black" stroke-width="2" fill="transparent"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<ngx-graph
|
||||
class="chart-container"
|
||||
[view]="[800, 550]"
|
||||
[links]="[
|
||||
{
|
||||
id: 'a',
|
||||
source: 'first',
|
||||
target: 'second',
|
||||
label: 'is parent of'
|
||||
}, {
|
||||
id: 'b',
|
||||
source: 'first',
|
||||
target: 'c1',
|
||||
label: 'custom label'
|
||||
}, {
|
||||
id: 'd',
|
||||
source: 'first',
|
||||
target: 'c2',
|
||||
label: 'custom label'
|
||||
}, {
|
||||
id: 'e',
|
||||
source: 'c1',
|
||||
target: 'd',
|
||||
label: 'first link'
|
||||
}, {
|
||||
id: 'f',
|
||||
source: 'c1',
|
||||
target: 'd',
|
||||
label: 'second link'
|
||||
}
|
||||
]"
|
||||
[nodes]="[
|
||||
{
|
||||
id: 'first',
|
||||
label: 'A'
|
||||
}, {
|
||||
id: 'second',
|
||||
label: 'B'
|
||||
}, {
|
||||
id: 'c1',
|
||||
label: 'C1'
|
||||
}, {
|
||||
id: 'c2',
|
||||
label: 'C2'
|
||||
}, {
|
||||
id: 'd',
|
||||
label: 'D'
|
||||
}
|
||||
]"
|
||||
[clusters]="[
|
||||
{
|
||||
id: 'third',
|
||||
label: 'Cluster node',
|
||||
childNodeIds: ['c1', 'c2']
|
||||
}
|
||||
]"
|
||||
layout="dagreCluster"
|
||||
(select)="handleNodeSelect($event)"
|
||||
>
|
||||
<ng-template #defsTemplate>
|
||||
<svg:marker id="arrow" viewBox="0 -5 10 10" refX="8" refY="0" markerWidth="4" markerHeight="4" orient="auto">
|
||||
<svg:path d="M0,-5L10,0L0,5" class="arrow-head" />
|
||||
</svg:marker>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #clusterTemplate let-cluster>
|
||||
<svg:g class="node cluster">
|
||||
<svg:rect
|
||||
rx="5"
|
||||
ry="5"
|
||||
[attr.width]="cluster.dimension.width"
|
||||
[attr.height]="cluster.dimension.height"
|
||||
[attr.fill]="cluster.data.color"
|
||||
/>
|
||||
</svg:g>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #nodeTemplate let-node>
|
||||
<svg:g class="node">
|
||||
<svg:rect
|
||||
[attr.width]="node.dimension.width"
|
||||
[attr.height]="node.dimension.height"
|
||||
[attr.fill]="node.data.color"
|
||||
/>
|
||||
<svg:text alignment-baseline="central" [attr.x]="10" [attr.y]="node.dimension.height / 2">
|
||||
{{node.label}}
|
||||
</svg:text>
|
||||
<!--<foreignObject width="100%" height="100%">
|
||||
<xhtml:div>
|
||||
<xhtml:div #source style="border:1px green solid;width: fit-content;margin-left:200px;margin-top:50px;">
|
||||
I'm a div inside a SVG.
|
||||
</xhtml:div>
|
||||
<xhtml:p #target style="border:1px green solid;width: fit-content;margin-left:10px;margin-top:120px">
|
||||
I'm a second div inside a SVG.
|
||||
</xhtml:p>
|
||||
</xhtml:div>
|
||||
</foreignObject>-->
|
||||
</svg:g>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #linkTemplate let-link>
|
||||
<svg:g class="edge">
|
||||
<svg:path class="line" stroke-width="2" marker-end="url(#arrow)"></svg:path>
|
||||
<svg:text class="edge-label" text-anchor="middle">
|
||||
<textPath
|
||||
class="text-path"
|
||||
[attr.href]="'#' + link.id"
|
||||
[style.dominant-baseline]="link.dominantBaseline"
|
||||
startOffset="50%"
|
||||
>
|
||||
{{link.label}}
|
||||
</textPath>
|
||||
</svg:text>
|
||||
</svg:g>
|
||||
</ng-template>
|
||||
</ngx-graph>
|
||||
</div>
|
||||
|
||||
<router-outlet />
|
||||
|
@ -1,44 +1,19 @@
|
||||
import {AfterViewInit, Component, ViewChild} from '@angular/core';
|
||||
import {Component} from "@angular/core";
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
import {GraphModule} from "./view/graph/graph.module";
|
||||
import { getBezierPath } from '@xyflow/system';
|
||||
import {DragDropModule} from '@angular/cdk/drag-drop';
|
||||
import {ChildView} from "./model/ViewModel";
|
||||
import {NgxGraphModule} from "@kr0san89/ngx-graph";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: true,
|
||||
imports: [RouterOutlet, GraphModule, DragDropModule],
|
||||
imports: [RouterOutlet, GraphModule, NgxGraphModule],
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.scss'
|
||||
})
|
||||
export class AppComponent implements AfterViewInit {
|
||||
@ViewChild('source') source?: ChildView
|
||||
@ViewChild('target') target?: ChildView
|
||||
@ViewChild('parent') parent?: ChildView
|
||||
@ViewChild('path') path?: ChildView<SVGPathElement>
|
||||
export class AppComponent {
|
||||
|
||||
ngAfterViewInit() {
|
||||
if(!this.source || !this.target || !this.parent || !this.path) return
|
||||
this.drawEdge(this.source.nativeElement, this.target.nativeElement, this.parent.nativeElement, this.path.nativeElement)
|
||||
}
|
||||
|
||||
handleMoved = () => {
|
||||
if(!this.source || !this.target || !this.parent || !this.path) return
|
||||
this.drawEdge(this.source.nativeElement, this.target.nativeElement, this.parent.nativeElement, this.path.nativeElement)
|
||||
}
|
||||
|
||||
private drawEdge(source: HTMLDivElement, target: HTMLDivElement, parent: HTMLDivElement, edge: SVGPathElement) {
|
||||
const sourceRect = source.getBoundingClientRect()
|
||||
const targetRect = target.getBoundingClientRect()
|
||||
const parentRect = parent.getBoundingClientRect()
|
||||
const path = getBezierPath({
|
||||
sourceX: sourceRect.x - parentRect.x + (sourceRect.width / 2),
|
||||
sourceY: sourceRect.y - parentRect.y - 1 + sourceRect.height,
|
||||
targetX: targetRect.x - parentRect.x + (targetRect.width / 2),
|
||||
targetY: targetRect.y - parentRect.y
|
||||
})
|
||||
edge.setAttribute('d', path[0])
|
||||
handleNodeSelect = (event: any) => {
|
||||
console.log('handleNodeSelect', event)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user