From 4a46cd505d790150fdb7cc396506369ee05afceb Mon Sep 17 00:00:00 2001 From: julius Date: Thu, 20 Feb 2025 08:54:56 +0100 Subject: [PATCH] feat: Network Graph with vis.js --- src/Network.tsx | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/Network.tsx diff --git a/src/Network.tsx b/src/Network.tsx new file mode 100644 index 0000000..24bbe99 --- /dev/null +++ b/src/Network.tsx @@ -0,0 +1,127 @@ +import { useEffect, useLayoutEffect, useRef, useState } from 'react'; +import "vis-network/styles/vis-network.css"; +import { apiAuth, baseUrl } from './api'; +import NetworkData, { Edge } from './types'; +import { Network } from 'vis-network/esnext'; +import { DataSet, DataView } from "vis-data/esnext"; + +const GraphComponent = () => { + const graphRef = useRef(null); + const [data, setData] = useState({ nodes: [], edges: [] } as NetworkData); + const [loading, setLoading] = useState(true); + + async function loadData() { + setLoading(true); + await apiAuth("analysis/json", null) + .then(json => json as Promise).then(json => { setData(json) }) + setLoading(false); + } + + useEffect(() => { loadData() }, []) + + var network: Network; + + //function updateEdgeWidths(nodeId: number | string) { + // // Get all edges connected to the clicked node + // const edges = network.body.edges.getEdges({ + // filter: (edge: any) => edge.from === nodeId, + // }); + // // Update the width of each edge + // edges.forEach((edge: any) => { + // network.body.edges.update(edge.id, { width: 5 }); // Change the width to your desired value + // }); + //} + + + useEffect(() => { + var { nodes, edges } = data; + if (graphRef.current) { + const options = { + layout: { + randomSeed: null, + }, + interaction: { + zoomView: true, + }, + nodes: { + shape: 'box', + size: 20, + font: { size: 24 }, + }, + edges: { + arrows: "to", + color: "black", + } + }; + + + const edgesFilterValues = { + likes: true, + dislikes: false, + } + const edgesFilter = (edge: Edge) => { + return edgesFilterValues[edge.relation]; + }; + + //edgeFilters.forEach((filter) => + // filter.addEventListener("change", (e) => { + // const { value, checked } = e.target; + // edgesFilterValues[value] = checked; + // edgesView.refresh(); + // }) + //); + + var networkData = { + nodes: new DataSet(nodes), + edges: new DataView(new DataSet(edges), { filter: edgesFilter }) + }; + network = new Network(graphRef.current, networkData, options); + + // Add event listeners for node clicks and drags + network.on('click', (params) => { + if (params.nodes.length > 0) { + console.log(`clicked ${networkData.nodes.getIds().find((nodeId) => nodeId === params.nodes[0])}`); + const nodeID = params.nodes[0]; + //updateEdgeWidths(nodeID); + + if (nodeID !== null) { + edges.forEach((edge) => { + if (edge.from === nodeID) { + edge.color = { opacity: 1, highlight: "red", color: "red" }; + } else { + edge.color = { opacity: 0.2, highlight: "none", color: "#36c" }; + } + }); + } else { + edges.forEach((edge) => { + edge.color = { opacity: 0.2, highlight: "none", color: "#36c" }; + }); + } + // + // Update the network with new edge colors + if (graphRef.current) { + const updatedData = { + nodes: new DataSet(nodes), + edges: new DataSet(edges), + }; + network.setData(updatedData); + } + } + }) + + network.on('dragEnd', (params) => { + if (params.nodes.length > 0) { + console.log(`dragged ${networkData.nodes.getIds().find((nodeId) => nodeId === params.nodes[0])}`); + } + }); + + } + }, [loading]); + + + if (loading) return + else + return
; +}; + +export default GraphComponent;