@@ -5,6 +5,9 @@ import { getGraph } from "../api";
55import { StatusBadge } from "./primitives/StatusBadge" ;
66import type { DependencyGraph as DependencyGraphModel , GraphEdge , GraphNode } from "../types" ;
77
8+ type GraphSimulationNode = GraphNode & d3 . SimulationNodeDatum ;
9+ type GraphSimulationLink = GraphEdge & d3 . SimulationLinkDatum < GraphSimulationNode > ;
10+
811interface GraphFilterState {
912 nodeTypes : Record < GraphNode [ "type" ] , boolean > ;
1013 platform : string ;
@@ -136,6 +139,8 @@ export function DependencyGraph() {
136139
137140 const root = svg . attr ( "viewBox" , `0 0 ${ width } ${ height } ` ) ;
138141 const canvas = root . append ( "g" ) ;
142+ const simulationNodes : GraphSimulationNode [ ] = visibleGraph . nodes . map ( ( node ) => ( { ...node } ) ) ;
143+ const simulationLinks : GraphSimulationLink [ ] = visibleGraph . edges . map ( ( edge ) => ( { ...edge } ) ) ;
139144
140145 root . call (
141146 d3 . zoom < SVGSVGElement , unknown > ( ) . scaleExtent ( [ 0.5 , 2 ] ) . on ( "zoom" , ( event : d3 . D3ZoomEvent < SVGSVGElement , unknown > ) => {
@@ -144,80 +149,80 @@ export function DependencyGraph() {
144149 ) ;
145150
146151 const simulation = d3
147- . forceSimulation ( visibleGraph . nodes as d3 . SimulationNodeDatum [ ] )
152+ . forceSimulation < GraphSimulationNode > ( simulationNodes )
148153 . force (
149154 "link" ,
150155 d3
151- . forceLink ( visibleGraph . edges as d3 . SimulationLinkDatum < d3 . SimulationNodeDatum > [ ] )
152- . id ( ( node : { id : string } ) => node . id )
153- . distance ( ( edge : any ) => ( edge . type === "backup" ? 150 : 120 ) ) ,
156+ . forceLink < GraphSimulationNode , GraphSimulationLink > ( simulationLinks )
157+ . id ( ( node ) => node . id )
158+ . distance ( ( edge ) => ( edge . type === "backup" ? 150 : 120 ) ) ,
154159 )
155160 . force ( "charge" , d3 . forceManyBody ( ) . strength ( - 280 ) )
156161 . force ( "center" , d3 . forceCenter ( width / 2 , height / 2 ) ) ;
157162
158163 const edges = canvas
159164 . append ( "g" )
160165 . selectAll ( "line" )
161- . data ( visibleGraph . edges )
166+ . data ( simulationLinks )
162167 . join ( "line" )
163- . attr ( "stroke" , ( edge : GraphEdge ) => edgeColor ( edge ) )
168+ . attr ( "stroke" , ( edge : GraphSimulationLink ) => edgeColor ( edge ) )
164169 . attr ( "stroke-width" , 1.75 )
165170 . attr ( "stroke-opacity" , 0.65 ) ;
166171
167172 const nodes = canvas
168173 . append ( "g" )
169- . selectAll < SVGCircleElement , GraphNode > ( "circle" )
170- . data ( visibleGraph . nodes )
174+ . selectAll < SVGCircleElement , GraphSimulationNode > ( "circle" )
175+ . data ( simulationNodes )
171176 . join ( "circle" )
172177 . attr ( "r" , ( node ) => ( node . id === selectedNodeId ? 18 : node . type === "vm" ? 14 : 12 ) )
173- . attr ( "fill" , ( node : GraphNode ) => nodeColor ( node ) )
178+ . attr ( "fill" , ( node : GraphSimulationNode ) => nodeColor ( node ) )
174179 . attr ( "stroke" , ( node ) => ( node . id === selectedNodeId ? "#0f172a" : "#ffffff" ) )
175180 . attr ( "stroke-width" , ( node ) => ( node . id === selectedNodeId ? 3 : 2 ) )
176181 . style ( "cursor" , "pointer" )
177182 . call (
178183 d3
179- . drag < SVGCircleElement , GraphNode > ( )
180- . on ( "start" , ( event : d3 . D3DragEvent < SVGCircleElement , GraphNode , GraphNode > , node : any ) => {
184+ . drag < SVGCircleElement , GraphSimulationNode > ( )
185+ . on ( "start" , ( event : d3 . D3DragEvent < SVGCircleElement , GraphSimulationNode , GraphSimulationNode > , node ) => {
181186 if ( ! event . active ) {
182187 simulation . alphaTarget ( 0.3 ) . restart ( ) ;
183188 }
184189 node . fx = node . x ;
185190 node . fy = node . y ;
186191 } )
187- . on ( "drag" , ( event : d3 . D3DragEvent < SVGCircleElement , GraphNode , GraphNode > , node : any ) => {
192+ . on ( "drag" , ( event : d3 . D3DragEvent < SVGCircleElement , GraphSimulationNode , GraphSimulationNode > , node ) => {
188193 node . fx = event . x ;
189194 node . fy = event . y ;
190195 } )
191- . on ( "end" , ( event : d3 . D3DragEvent < SVGCircleElement , GraphNode , GraphNode > , node : any ) => {
196+ . on ( "end" , ( event : d3 . D3DragEvent < SVGCircleElement , GraphSimulationNode , GraphSimulationNode > , node ) => {
192197 if ( ! event . active ) {
193198 simulation . alphaTarget ( 0 ) ;
194199 }
195200 node . fx = null ;
196201 node . fy = null ;
197202 } ) ,
198203 )
199- . on ( "click" , ( _event : MouseEvent , node : GraphNode ) => setSelectedNodeId ( node . id ) ) ;
204+ . on ( "click" , ( _event : MouseEvent , node : GraphSimulationNode ) => setSelectedNodeId ( node . id ) ) ;
200205
201- nodes . append ( "title" ) . text ( ( node : GraphNode ) => node . label ) ;
206+ nodes . append ( "title" ) . text ( ( node : GraphSimulationNode ) => node . label ) ;
202207
203208 const labels = canvas
204209 . append ( "g" )
205210 . selectAll ( "text" )
206- . data ( visibleGraph . nodes )
211+ . data ( simulationNodes )
207212 . join ( "text" )
208213 . attr ( "font-size" , 12 )
209214 . attr ( "fill" , "#0f172a" )
210- . text ( ( node : GraphNode ) => node . label ) ;
215+ . text ( ( node : GraphSimulationNode ) => node . label ) ;
211216
212217 simulation . on ( "tick" , ( ) => {
213218 edges
214- . attr ( "x1" , ( edge : any ) => edge . source . x )
215- . attr ( "y1" , ( edge : any ) => edge . source . y )
216- . attr ( "x2" , ( edge : any ) => edge . target . x )
217- . attr ( "y2" , ( edge : any ) => edge . target . y ) ;
219+ . attr ( "x1" , ( edge ) => ( typeof edge . source === "object" ? edge . source . x ?? 0 : 0 ) )
220+ . attr ( "y1" , ( edge ) => ( typeof edge . source === "object" ? edge . source . y ?? 0 : 0 ) )
221+ . attr ( "x2" , ( edge ) => ( typeof edge . target === "object" ? edge . target . x ?? 0 : 0 ) )
222+ . attr ( "y2" , ( edge ) => ( typeof edge . target === "object" ? edge . target . y ?? 0 : 0 ) ) ;
218223
219- nodes . attr ( "cx" , ( node : any ) => node . x ) . attr ( "cy" , ( node : any ) => node . y ) ;
220- labels . attr ( "x" , ( node : any ) => node . x + 18 ) . attr ( "y" , ( node : any ) => node . y + 4 ) ;
224+ nodes . attr ( "cx" , ( node ) => node . x ?? 0 ) . attr ( "cy" , ( node ) => node . y ?? 0 ) ;
225+ labels . attr ( "x" , ( node ) => ( node . x ?? 0 ) + 18 ) . attr ( "y" , ( node ) => ( node . y ?? 0 ) + 4 ) ;
221226 } ) ;
222227
223228 return ( ) => {
0 commit comments