@@ -6,6 +6,7 @@ import { DataStore } from 'src/app/model/data-store';
66
77export interface graphNodes {
88 id : string ;
9+ relativeLevel : number ;
910}
1011
1112export interface graphLinks {
@@ -58,7 +59,7 @@ export class DependencyGraphComponent implements OnInit {
5859 this . addNode ( activity . name ) ;
5960 if ( activity . dependsOn ) {
6061 for ( const prececcor of activity . dependsOn ) {
61- this . addNode ( prececcor ) ;
62+ this . addNode ( prececcor , - 1 ) ;
6263 this . graphData [ 'links' ] . push ( {
6364 source : prececcor ,
6465 target : activity . name ,
@@ -71,7 +72,7 @@ export class DependencyGraphComponent implements OnInit {
7172 const all : Activity [ ] = this . dataStore . activityStore ?. getAllActivities ?.( ) ?? [ ] ;
7273 for ( const activity of all ) {
7374 if ( activity . dependsOn ?. includes ( currentActivity . name ) ) {
74- this . addNode ( activity . name ) ;
75+ this . addNode ( activity . name , 1 ) ;
7576 this . graphData [ 'links' ] . push ( {
7677 source : currentActivity . name ,
7778 target : activity . name ,
@@ -80,9 +81,9 @@ export class DependencyGraphComponent implements OnInit {
8081 }
8182 }
8283
83- addNode ( activityName : string ) {
84+ addNode ( activityName : string , relativeLevel : number = 0 ) : void {
8485 if ( ! this . visited . has ( activityName ) ) {
85- this . graphData [ 'nodes' ] . push ( { id : activityName } ) ;
86+ this . graphData [ 'nodes' ] . push ( { id : activityName , relativeLevel : relativeLevel } ) ;
8687 this . visited . add ( activityName ) ;
8788 }
8889 }
@@ -92,13 +93,16 @@ export class DependencyGraphComponent implements OnInit {
9293
9394 this . simulation = d3
9495 . forceSimulation ( )
95- . force (
96- 'link' ,
97- d3 . forceLink ( ) . id ( function ( d : any ) {
96+ . force ( 'link' , d3 . forceLink ( ) . id ( function ( d : any ) {
9897 return d . id ;
99- } )
100- )
101- . force ( 'charge' , d3 . forceManyBody ( ) . strength ( - 12000 ) )
98+ } ) )
99+ . force ( 'x' , d3 . forceX ( ( d : any ) => {
100+ return d . relativeLevel * 300 ;
101+ } ) . strength ( 10 ) )
102+ . force ( 'y' , d3 . forceY ( ( d : any ) => {
103+ return d . relativeLevel * 30 ;
104+ } ) . strength ( 10 ) )
105+ . force ( 'charge' , d3 . forceManyBody ( ) . strength ( - 8000 ) )
102106 . force ( 'center' , d3 . forceCenter ( 0 , 0 ) ) ;
103107
104108 svg
@@ -137,22 +141,42 @@ export class DependencyGraphComponent implements OnInit {
137141 . append ( 'g' ) ;
138142 /* eslint-enable */
139143
140- var defaultNodeColor = this . COLOR_OF_NODE ;
141- node
142- . append ( 'circle' )
143- . attr ( 'r' , 10 )
144- . attr ( 'fill' , function ( d ) {
145- if ( d . id == activityName ) return 'yellow' ;
146- else return defaultNodeColor ;
147- } ) ;
148144
149- node
150- . append ( 'text' )
151- . attr ( 'dy' , '.35em' )
145+
146+ var defaultNodeColor = this . COLOR_OF_NODE ;
147+ const rectHeight = 30 ;
148+ const rectRx = 10 ;
149+ const rectRy = 10 ;
150+ const padding = 20 ;
151+
152+ // Append text first so we can measure it
153+ node . append ( 'text' )
154+ . attr ( 'dy' , '0.35em' )
152155 . attr ( 'text-anchor' , 'middle' )
153- . text ( function ( d ) {
154- return d . id ;
155- } ) ;
156+ . text ( function ( d ) { return d . id ; } ) ;
157+
158+ // Now for each node, measure the text and insert a rect behind it
159+ const self = this ;
160+ node . each ( function ( this : SVGGElement , d : any ) {
161+ const textElem = d3 . select ( this ) . select ( 'text' ) . node ( ) as SVGTextElement ;
162+ let textWidth = 60 ; // fallback default
163+ if ( textElem && textElem . getBBox ) {
164+ textWidth = textElem . getBBox ( ) . width ;
165+ }
166+ const rectWidth = textWidth + padding ;
167+ // Insert rect before text
168+ d3 . select ( this )
169+ . insert ( 'rect' , 'text' )
170+ . attr ( 'x' , - rectWidth / 2 )
171+ . attr ( 'y' , - rectHeight / 2 )
172+ . attr ( 'width' , rectWidth )
173+ . attr ( 'height' , rectHeight )
174+ . attr ( 'rx' , rectRx )
175+ . attr ( 'ry' , rectRy )
176+ . attr ( 'fill' , ( d : any ) => d . id == activityName ? 'yellow' : defaultNodeColor )
177+ . attr ( 'stroke' , self . BORDER_COLOR_OF_NODE )
178+ . attr ( 'stroke-width' , 1.5 ) ;
179+ } ) ;
156180
157181 this . simulation . nodes ( this . graphData [ 'nodes' ] ) . on ( 'tick' , ticked ) ;
158182
0 commit comments