@@ -43,6 +43,8 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
4343 private tooltip : d3 . Selection < HTMLDivElement , unknown , HTMLElement , undefined > ;
4444 private simulation : Simulation < DashboardSplitsPeerSimulation , undefined > ;
4545 private circles : d3 . Selection < SVGCircleElement , DashboardSplitsPeerSimulation , SVGGElement , undefined > ;
46+ private webnodeInnerCircles : d3 . Selection < SVGCircleElement , DashboardSplitsPeerSimulation , SVGGElement , undefined > ;
47+ private webnodeOuterCircles : d3 . Selection < SVGCircleElement , DashboardSplitsPeerSimulation , SVGGElement , undefined > ;
4648 private triangles : d3 . Selection < SVGPathElement , DashboardSplitsPeerSimulation , SVGGElement , undefined > ;
4749 private squares : d3 . Selection < SVGRectElement , DashboardSplitsPeerSimulation , SVGGElement , undefined > ;
4850 private diamonds : d3 . Selection < SVGPathElement , DashboardSplitsPeerSimulation , SVGGElement , undefined > ;
@@ -158,7 +160,8 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
158160 console . log ( 'Spectral Gap:' , spectralGap ) ;
159161
160162 this . renderGraph ( { peers, links, sets } ) ;
161- } , tap ( ( { fetching } ) => {
163+ } ,
164+ tap ( ( { fetching } ) => {
162165 if ( fetching ) {
163166 this . fetching = fetching ;
164167 }
@@ -245,7 +248,8 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
245248 . attr ( 'class' , d => `link ${ d . source . address } ${ d . target . address } ` )
246249 . attr ( 'stroke' , 'var(--base-divider)' ) ;
247250
248- const circleNodes = nodes . filter ( peer => ! peer . node || [ 'node' , 'generator' ] . some ( n => peer . node . toLowerCase ( ) . includes ( n ) ) ) ;
251+ const circleNodes = nodes . filter ( peer => ! peer . node || [ 'node' , 'generator' ] . some ( n => peer . node . toLowerCase ( ) . includes ( n ) && ! peer . node . toLowerCase ( ) . includes ( 'webnode' ) ) ) ;
252+ const webnodeNodes = nodes . filter ( p => p . node ) . filter ( peer => peer . node . toLowerCase ( ) . includes ( 'webnode' ) ) ;
249253 const triangleNodes = nodes . filter ( p => p . node ) . filter ( peer => peer . node . toLowerCase ( ) . includes ( 'snark' ) ) ;
250254 const squareNodes = nodes . filter ( p => p . node ) . filter ( peer => peer . node . toLowerCase ( ) . includes ( 'prod' ) ) ;
251255 const diamondNodes = nodes . filter ( p => p . node ) . filter ( peer => peer . node . toLowerCase ( ) . includes ( 'seed' ) ) ;
@@ -259,6 +263,34 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
259263 . attr ( 'r' , ( d : DashboardSplitsPeerSimulation ) => d . radius ) ;
260264 this . addCommonProperties ( this . circles , lines ) ;
261265
266+ this . webnodeOuterCircles = this . getG ( 'webnodes-outer' , 'circle' )
267+ . attr ( 'class' , 'webnodes-outer' )
268+ . selectAll ( 'circle' )
269+ . data ( webnodeNodes )
270+ . enter ( )
271+ . append ( 'circle' )
272+ . attr ( 'r' , ( d : DashboardSplitsPeerSimulation ) => d . radius )
273+ . attr ( 'fill' , 'none' )
274+ this . addCommonProperties ( this . webnodeOuterCircles , lines , true ) ;
275+
276+ this . webnodeInnerCircles = this . getG ( 'webnodes-inner' , 'circle' )
277+ . attr ( 'class' , 'webnodes-inner' )
278+ . selectAll ( 'circle' )
279+ . data ( webnodeNodes )
280+ . enter ( )
281+ . append ( 'circle' )
282+ . attr ( 'r' , ( d : DashboardSplitsPeerSimulation ) => d . radius * 0.7 )
283+ . attr ( 'fill' , 'var(--success-primary)' )
284+ . on ( 'mouseover' , ( event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => this . mouseOverHandle ( peer , event , true ) )
285+ . on ( 'mouseout' , ( event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => this . mouseOutHandler ( peer , event , true ) )
286+ . on ( 'click' , ( _event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => {
287+ let selectedPeer = this . peers . find ( p => p . address === peer . address ) ;
288+ if ( selectedPeer === this . activePeer ) {
289+ selectedPeer = undefined ;
290+ }
291+ this . dispatch ( DashboardSplitsSetActivePeer , selectedPeer ) ;
292+ } )
293+
262294 this . triangles = this . getG ( 'triangles' , 'path' )
263295 . attr ( 'class' , 'triangles' )
264296 . selectAll ( 'path' )
@@ -291,6 +323,30 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
291323 private createSimulation ( sets : DashboardSplitsSet [ ] , nodes : DashboardSplitsPeerSimulation [ ] , lines : DashboardSplitsLinkSimulation [ ] ) : void {
292324 const numberOfSets = sets . length ;
293325 const matrixSize = Math . ceil ( Math . sqrt ( numberOfSets ) ) ;
326+ const getRepulsion = ( sets : number ) => {
327+ switch ( sets ) {
328+ case 1 :
329+ return 30 ;
330+ case 2 :
331+ return 25 ;
332+ case 3 :
333+ return 22 ;
334+ case 4 :
335+ return 20 ;
336+ case 5 :
337+ return 15 ;
338+ case 6 :
339+ return 12 ;
340+ case 7 :
341+ return 9 ;
342+ case 8 :
343+ return 7 ;
344+ case 9 :
345+ return 5 ;
346+ default :
347+ return 2 ;
348+ }
349+ }
294350 this . simulation = d3 . forceSimulation < DashboardSplitsPeerSimulation > ( nodes )
295351 . force ( 'link' , d3 . forceLink ( lines ) . distance ( numberOfSets === 1 ? 250 : 100 ) ) // This adds links between nodes and sets the distance between them
296352 . force ( 'charge' , d3 . forceManyBody ( ) . strength ( - 30 ) ) // control the repulsion between groups - negative means bigger distance
@@ -310,7 +366,7 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
310366 }
311367 return this . height ;
312368 } ) . strength ( 0.05 ) )
313- . force ( 'collide' , d3 . forceCollide ( ) . radius ( numberOfSets < 3 ? 25 : 17 ) ) // This adds repulsion between nodes. Play with the radius
369+ . force ( 'collide' , d3 . forceCollide ( ) . radius ( getRepulsion ( numberOfSets ) ) ) // This adds repulsion between nodes. Play with the radius
314370 . force ( 'center' , d3 . forceCenter ( this . width / 2 , this . height / 2 ) )
315371 . force ( 'bounds' , ( ) => {
316372 for ( let node of nodes ) {
@@ -331,6 +387,12 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
331387 this . circles
332388 . attr ( 'cx' , ( d : DashboardSplitsPeerSimulation ) => d . x )
333389 . attr ( 'cy' , ( d : DashboardSplitsPeerSimulation ) => d . y ) ;
390+ this . webnodeInnerCircles
391+ . attr ( 'cx' , ( d : DashboardSplitsPeerSimulation ) => d . x )
392+ . attr ( 'cy' , ( d : DashboardSplitsPeerSimulation ) => d . y ) ;
393+ this . webnodeOuterCircles
394+ . attr ( 'cx' , ( d : DashboardSplitsPeerSimulation ) => d . x )
395+ . attr ( 'cy' , ( d : DashboardSplitsPeerSimulation ) => d . y ) ;
334396 this . triangles
335397 . attr ( 'transform' , ( d : DashboardSplitsPeerSimulation ) => `translate(${ d . x } , ${ d . y } )` ) ;
336398 this . squares
@@ -346,14 +408,14 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
346408 this . simulation . alpha ( 0.1 ) ; // controls how much the animation lasts
347409 }
348410
349- private addCommonProperties ( selection : d3 . Selection < any , DashboardSplitsPeerSimulation , SVGGElement , undefined > , lines : DashboardSplitsLinkSimulation [ ] ) : void {
411+ private addCommonProperties ( selection : d3 . Selection < any , DashboardSplitsPeerSimulation , SVGGElement , undefined > , lines : DashboardSplitsLinkSimulation [ ] , noColorChange : boolean = false ) : void {
350412 selection
351413 . attr ( 'fill' , 'var(--special-node)' )
352414 . attr ( 'stroke' , ( d : DashboardSplitsPeerSimulation ) => `var(--${ lines . some ( link => link . source . address === d . address || link . target . address === d . address ) ? 'success' : 'warn' } -primary)` )
353415 . attr ( 'stroke-width' , 1 )
354- . on ( 'mouseover' , ( event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => this . mouseOverHandle ( peer , event ) )
355- . on ( 'mouseout' , ( event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => this . mouseOutHandler ( peer , event ) )
356- . on ( 'click' , ( event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => {
416+ . on ( 'mouseover' , ( event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => this . mouseOverHandle ( peer , event , noColorChange ) )
417+ . on ( 'mouseout' , ( event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => this . mouseOutHandler ( peer , event , noColorChange ) )
418+ . on ( 'click' , ( _event : MouseEvent & { target : HTMLElement } , peer : DashboardSplitsPeerSimulation ) => {
357419 let selectedPeer = this . peers . find ( p => p . address === peer . address ) ;
358420 if ( selectedPeer === this . activePeer ) {
359421 selectedPeer = undefined ;
@@ -372,7 +434,7 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
372434 . attr ( 'class' , cls ) ;
373435 }
374436
375- private mouseOverHandle ( peer : DashboardSplitsPeerSimulation , event : MouseEvent & { target : HTMLElement } ) : void {
437+ private mouseOverHandle ( peer : DashboardSplitsPeerSimulation , event : MouseEvent & { target : HTMLElement } , noColorChange : boolean = false ) : void {
376438 const selection = this . tooltip . html ( `${ peer . node || peer . address } , <span class="tertiary">→</span> ${ peer . incomingConnections } <span class="tertiary">/</span> ${ peer . outgoingConnections } <span class="tertiary">→</span>` )
377439 . style ( 'display' , 'block' ) ;
378440
@@ -386,7 +448,9 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
386448 if ( this . activePeer ?. address === peer . address ) {
387449 return ;
388450 }
389- d3 . select ( event . target ) . attr ( 'fill' , 'var(--special-node-selected)' ) ;
451+ if ( ! noColorChange ) {
452+ d3 . select ( event . target ) . attr ( 'fill' , 'var(--special-node-selected)' ) ;
453+ }
390454 this . hoveredConnectedLinks = this . connections . filter ( link => {
391455 const isDirectConnection = link . source . address === peer . address || link . target . address === peer . address ;
392456 if ( this . activePeer ) {
@@ -398,12 +462,14 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
398462 this . hoveredConnectedLinks . attr ( 'stroke' , 'var(--success-primary)' ) ;
399463 }
400464
401- private mouseOutHandler ( peer : DashboardSplitsPeerSimulation , event : MouseEvent & { target : HTMLElement } ) : void {
465+ private mouseOutHandler ( peer : DashboardSplitsPeerSimulation , event : MouseEvent & { target : HTMLElement } , noColorChange : boolean = false ) : void {
402466 this . tooltip . style ( 'display' , 'none' ) ;
403467 if ( this . activePeer ?. address === peer . address ) {
404468 return ;
405469 }
406- d3 . select ( event . target ) . attr ( 'fill' , 'var(--special-node)' ) ;
470+ if ( ! noColorChange ) {
471+ d3 . select ( event . target ) . attr ( 'fill' , 'var(--special-node)' ) ;
472+ }
407473 this . hoveredConnectedLinks . attr ( 'stroke' , 'var(--base-divider)' ) ;
408474 }
409475}
0 commit comments