Add router to allow for both viz simult

This commit is contained in:
William Jeynes
2026-04-24 17:28:31 +01:00
parent 8fcba8d775
commit 9aca9855c0
4 changed files with 43 additions and 30 deletions
+30
View File
@@ -0,0 +1,30 @@
import { useEffect, useState } from "react";
import { VizSmallConnected } from "./VizSmallConnected";
import { VizTimeFilter } from "./VizTimeFilter";
function Home() {
return (
<div>
<h1>Will Jeynes - LLMs for Disinformation Analysis - Graph Visualisations</h1>
<p><a href="#small">Default</a></p>
<p><a href="#time">Time-Filter</a></p>
</div>
);
}
export function AppRouter() {
const [route, setRoute] = useState(() => window.location.hash);
useEffect(() => {
const onHashChange = () => {
setRoute(window.location.hash);
};
window.addEventListener("hashchange", onHashChange);
return () => window.removeEventListener("hashchange", onHashChange);
}, []);
console.log(route)
if (route === "#small") return <VizSmallConnected />;
if (route === "#time") return <VizTimeFilter />;
return <Home />;
}
@@ -93,7 +93,7 @@ function getConnectedComponents(nodes, links) {
return components; return components;
} }
export function App() { export function VizSmallConnected() {
const fgRef = useRef(); const fgRef = useRef();
const [selectedNode, setSelectedNode] = useState(null); const [selectedNode, setSelectedNode] = useState(null);
const [minGraphSize, setMinGraphSize] = useState(10); const [minGraphSize, setMinGraphSize] = useState(10);
@@ -223,6 +223,7 @@ export function App() {
maxWidth: "500px" maxWidth: "500px"
}} }}
> >
<p><a href="#home">Go Home</a></p>
<h2>Config</h2> <h2>Config</h2>
<label> <label>
Min connected graph size: <strong>{minGraphSize}</strong> Min connected graph size: <strong>{minGraphSize}</strong>
@@ -29,11 +29,6 @@ function parseDateSafe(dateStr) {
return d; return d;
} }
function monthsDiff(a, b) {
const ms = Math.abs(a - b);
return ms / (1000 * 60 * 60 * 24 * 30.44);
}
function buildLookupMaps(data) { function buildLookupMaps(data) {
const claimMap = new Map(data.claims.map(c => [c.id, c])); const claimMap = new Map(data.claims.map(c => [c.id, c]));
const eventMap = new Map(data.events.map(e => [e.id, e])); const eventMap = new Map(data.events.map(e => [e.id, e]));
@@ -136,7 +131,7 @@ function getConnectedComponents(nodes, links) {
return components; return components;
} }
export function App2() { export function VizTimeFilter() {
const fgRef = useRef(); const fgRef = useRef();
const [selectedNode, setSelectedNode] = useState(null); const [selectedNode, setSelectedNode] = useState(null);
const [inputDate, setInputDate] = useState(Date.now()); const [inputDate, setInputDate] = useState(Date.now());
@@ -261,18 +256,11 @@ export function App2() {
const radius = Math.min(10, fontSize * 0.6); const radius = Math.min(10, fontSize * 0.6);
let isHighlighted = false;
if (parsedInputDate && node.avgDate) {
const diffMonths = monthsDiff(parsedInputDate, node.avgDate);
isHighlighted = diffMonths <= 6;
}
ctx.fillStyle = node.type.includes("claim") ctx.fillStyle = node.type.includes("claim")
? "blue" ? "blue"
: "green" : "green"
if (isHighlighted) { if (highlightedNodeIds.has(node.id)) {
drawRoundedRect(ctx, x, y, width, height, radius); drawRoundedRect(ctx, x, y, width, height, radius);
ctx.fill(); ctx.fill();
ctx.strokeStyle = "white"; ctx.strokeStyle = "white";
@@ -291,13 +279,7 @@ export function App2() {
node.__bckgPos = { x, y }; node.__bckgPos = { x, y };
}} }}
nodePointerAreaPaint={(node, color, ctx) => { nodePointerAreaPaint={(node, color, ctx) => {
let isHighlighted = false; if (!highlightedNodeIds.has(node.id)) return;
if (parsedInputDate && node.avgDate) {
const diffMonths = monthsDiff(parsedInputDate, node.avgDate);
isHighlighted = diffMonths <= 6;
}
if (!isHighlighted) return;
const dims = node.__bckgDimensions; const dims = node.__bckgDimensions;
const pos = node.__bckgPos; const pos = node.__bckgPos;
@@ -321,11 +303,10 @@ export function App2() {
maxWidth: "500px" maxWidth: "500px"
}} }}
> >
<p><a href="#home">Go Home</a></p>
<h2>Details</h2> <h2>Details</h2>
{selectedNode ? ( {selectedNode ? (
<div> <div>
<p><strong>Title:</strong> {selectedNode.label}</p> <p><strong>Title:</strong> {selectedNode.label}</p>
<p><strong>Date: </strong>{new Date(selectedNode.avgDate).toISOString().slice(0, 10)}</p> <p><strong>Date: </strong>{new Date(selectedNode.avgDate).toISOString().slice(0, 10)}</p>
{selectedNode.members && ( {selectedNode.members && (
+6 -5
View File
@@ -1,11 +1,12 @@
import { createRoot } from 'react-dom/client'; import { createRoot } from "react-dom/client";
import { StrictMode } from 'react'; import { StrictMode } from "react";
import { App2 } from './App2'; import { AppRouter } from "./AppRouter";
let container = document.getElementById("app")!; let container = document.getElementById("app")!;
let root = createRoot(container) let root = createRoot(container);
root.render( root.render(
<StrictMode> <StrictMode>
<App2 /> <AppRouter />
</StrictMode> </StrictMode>
); );