11import React , { useEffect , useRef , useState } from "react" ;
22import * as VisNetwork from "vis-network" ;
3- import { HostId } from "./Stats" ;
3+ import { HostId , Stats } from "./Stats" ;
44
55import styles from "./Graph.module.css" ;
6-
7- const fetchData = async ( ) : Promise < string > => {
8- const response = await window . fetch ( "/api/v1/stats" , {
9- method : "GET" ,
10- headers : {
11- "Accept" : "text/vnd.graphviz; q=1.0"
12- }
13- } ) ;
14- return response . text ( ) ;
15- }
6+ import { Seq } from "immutable" ;
167
178export interface GraphProps {
9+ maybeStats : Stats | null ;
1810 maybeSelectedHostId : HostId | null ,
1911 setMaybeSelectedHostId : ( maybeSelectedHostId : HostId | null ) => void ,
2012}
@@ -26,34 +18,63 @@ export const Graph: React.FC<GraphProps> =
2618 const networkRef = useRef < VisNetwork . Network | null > ( null ) ;
2719
2820 useEffect ( ( ) => {
29- if ( containerRef . current === null ) {
21+ if ( containerRef . current === null
22+ || props . maybeStats === null ) {
3023 return ;
3124 }
3225 const container = containerRef . current ;
26+ const stats = props . maybeStats ;
3327
3428 setIsLoading ( true ) ;
35- fetchData ( ) . then ( data => {
36- // @ts -ignore
37- const parsedData = VisNetwork . parseDOTNetwork ( data ) ;
38- parsedData . options . physics = {
29+ const hostNodes : Seq . Indexed < VisNetwork . Node > =
30+ stats . hosts
31+ . entrySeq ( )
32+ . map ( ( [ hostId , host ] ) => ( {
33+ id : hostId ,
34+ label : host . hostname ,
35+ } ) ) ;
36+ const unmonitoredHostNodes : Seq . Indexed < VisNetwork . Node > =
37+ stats . unmonitoredHosts
38+ . entrySeq ( )
39+ . map ( ( [ hostId , unmonitoredHost ] ) => ( {
40+ id : hostId ,
41+ label : unmonitoredHost . host ,
42+ } ) ) ;
43+ const edges : Seq . Indexed < VisNetwork . Edge > =
44+ stats . hosts
45+ . entrySeq ( )
46+ . flatMap ( ( [ hostId , host ] ) =>
47+ host . connections
48+ . entrySeq ( )
49+ . map ( ( [ otherHostId , _ ] ) => ( {
50+ from : hostId ,
51+ to : otherHostId ,
52+ } ) )
53+ ) ;
54+ const data : VisNetwork . Data = {
55+ nodes : hostNodes . concat ( unmonitoredHostNodes ) . toArray ( ) ,
56+ edges : edges . toArray ( ) ,
57+ } ;
58+ const options : VisNetwork . Options = {
59+ physics : {
3960 solver : "forceAtlas2Based"
40- } ;
41- const network = new VisNetwork . Network ( container , parsedData ) ;
42- network . on ( "selectNode" , ( event ) => {
43- props . setMaybeSelectedHostId ( event . nodes [ 0 ] ) ;
44- } ) ;
45- network . on ( "afterDrawing" , ( _ ) => {
46- setIsLoading ( false ) ;
47- } ) ;
48- networkRef . current = network ;
49- } ) . catch ( console . error ) ;
61+ }
62+ } ;
63+ const network = new VisNetwork . Network ( container , data , options ) ;
64+ network . on ( "selectNode" , ( event ) => {
65+ props . setMaybeSelectedHostId ( event . nodes [ 0 ] ) ;
66+ } ) ;
67+ network . on ( "afterDrawing" , ( _ ) => {
68+ setIsLoading ( false ) ;
69+ } ) ;
70+ networkRef . current = network ;
5071
5172 return ( ) => {
5273 if ( networkRef . current !== null ) {
5374 networkRef . current . destroy ( ) ;
5475 }
5576 }
56- } , [ containerRef ] ) ;
77+ } , [ containerRef , props . maybeStats ] ) ;
5778
5879 useEffect ( ( ) => {
5980 if ( networkRef . current !== null && props . maybeSelectedHostId !== null ) {
@@ -62,7 +83,7 @@ export const Graph: React.FC<GraphProps> =
6283 } , [ networkRef , props . maybeSelectedHostId ] ) ;
6384
6485 return < section >
65- { isLoading && < span className = { styles . loading } > Loading…</ span > }
86+ { isLoading && < span className = { styles . loading } > Loading…</ span > }
6687 < div className = { styles . container } ref = { containerRef } > </ div >
6788 </ section > ;
6889 } ;
0 commit comments