From c34c901ffb299c89ecbd38e5149424a93cb985f4 Mon Sep 17 00:00:00 2001 From: William Jeynes Date: Tue, 28 Apr 2026 22:46:25 +0100 Subject: [PATCH] Add directional arrows. Apply same face lift to time filtering --- graphviz/frontend/src/Home.tsx | 2 +- graphviz/frontend/src/VizSmallConnected.tsx | 19 ++- graphviz/frontend/src/VizTimeFilter.tsx | 135 +++++++----------- .../frontend/src/utils/FloatingPanelStack.tsx | 13 +- 4 files changed, 67 insertions(+), 102 deletions(-) diff --git a/graphviz/frontend/src/Home.tsx b/graphviz/frontend/src/Home.tsx index 06dff49..8572f5a 100644 --- a/graphviz/frontend/src/Home.tsx +++ b/graphviz/frontend/src/Home.tsx @@ -73,7 +73,7 @@ export function Home() { href="https://github.com/WillJeynes/LLMsForDisinformationPrediction/" className="block bg-white rounded-xl px-4 py-2 underline text-center w-64 m-1" > - Project Source Code + Site Source Code diff --git a/graphviz/frontend/src/VizSmallConnected.tsx b/graphviz/frontend/src/VizSmallConnected.tsx index 99b8740..9cc3998 100644 --- a/graphviz/frontend/src/VizSmallConnected.tsx +++ b/graphviz/frontend/src/VizSmallConnected.tsx @@ -159,7 +159,7 @@ export function VizSmallConnected() { useEffect(() => { if (fgRef.current) { - fgRef.current.zoom(0.01, 0); + fgRef.current.zoom(0.05, 0); } }, []); @@ -174,7 +174,8 @@ export function VizSmallConnected() { linkColor={() => "black"} linkWidth={2.5} onNodeClick={(node) => setSelectedNode(node)} - + linkDirectionalArrowLength={100} + linkDirectionalArrowRelPos={0.9} nodeCanvasObject={(node, ctx, globalScale) => { const label = node.label; const fontSize = 16 + 32 * node.members.length; @@ -190,10 +191,10 @@ export function VizSmallConnected() { const x = node.x - width / 2; const y = node.y - height / 2; - const radius = Math.min(10, fontSize * 0.6); + const radius = node.type.includes("claim") ? fontSize * 6 : 0; // background - ctx.fillStyle = node.type.includes("claim") ? "blue" : "green"; + ctx.fillStyle = node.type.includes("claim") ? "DarkMagenta" : "green"; drawRoundedRect(ctx, x, y, width, height, radius); ctx.fill(); @@ -227,10 +228,10 @@ export function VizSmallConnected() { -

Trigger Event Cluster

-

Claim Cluster

+

Trigger Event Cluster

+

Claim Cluster

- + @@ -243,11 +244,7 @@ export function VizSmallConnected() { onChange={(e) => setMinGraphSize(Number(e.target.value))} /> -
- - - ); } \ No newline at end of file diff --git a/graphviz/frontend/src/VizTimeFilter.tsx b/graphviz/frontend/src/VizTimeFilter.tsx index b2fac94..ed19eaf 100644 --- a/graphviz/frontend/src/VizTimeFilter.tsx +++ b/graphviz/frontend/src/VizTimeFilter.tsx @@ -4,6 +4,10 @@ import * as d3 from "d3-force-3d"; import data from "./data_date.json"; import titlesData from "./titles_date.json"; +import HomeButton from "./utils/HomeButton"; +import { FloatingPanelStack } from "./utils/FloatingPanelStack"; +import { DetailsPanel } from "./utils/DetailsPanel"; +import { FloatingPanel } from "./utils/FloatingPanel"; function drawRoundedRect(ctx, x, y, width, height, radius) { const r = Math.min(radius, width / 2, height / 2); @@ -136,6 +140,7 @@ export function VizTimeFilter() { const [selectedNode, setSelectedNode] = useState(null); const [inputDate, setInputDate] = useState(1682353753000); //some time in 2023 const [showAll, setShowAll] = useState(false); + const [filterLeeway, setFilterLeeway] = useState(6); const parsedInputDate = useMemo(() => { const d = new Date(inputDate); @@ -200,7 +205,7 @@ export function VizTimeFilter() { function isNodeHighlighted(node, referenceDate) { if (!referenceDate || !node.avgDate) return false; const diffMonths = Math.abs(referenceDate - node.avgDate) / (1000 * 60 * 60 * 24 * 30.44); - return diffMonths <= 6; + return diffMonths <= filterLeeway; } const highlightedNodeIds = useMemo(() => { @@ -215,21 +220,24 @@ export function VizTimeFilter() { }); return set; - }, [graphData.nodes, parsedInputDate, showAll]); + }, [graphData.nodes, parsedInputDate, showAll, filterLeeway]); useEffect(() => { - if (fgRef.current) { - fgRef.current.zoom(0.01, 0); - } -}, []); + if (fgRef.current) { + fgRef.current.zoom(0.01, 0); + } + }, []); return (
+ node.label} nodeAutoColorBy="type" + linkDirectionalArrowLength={500} + linkDirectionalArrowRelPos={0.9} linkColor={(link) => { const sourceId = typeof link.source === "object" ? link.source.id : link.source; @@ -241,7 +249,7 @@ export function VizTimeFilter() { highlightedNodeIds.has(sourceId) && highlightedNodeIds.has(targetId); - return bothHighlighted ? "orange" : "rgba(0,0,0,0)"; + return bothHighlighted ? "black" : "rgba(0,0,0,0)"; }} linkWidth={2.5} onNodeClick={(node) => setSelectedNode(node)} @@ -260,10 +268,10 @@ export function VizTimeFilter() { const x = node.x - width / 2; const y = node.y - height / 2; - const radius = Math.min(10, fontSize * 0.6); + const radius = node.type.includes("claim") ? fontSize * 6 : 0; ctx.fillStyle = node.type.includes("claim") - ? "blue" + ? "DarkMagenta" : "green" if (highlightedNodeIds.has(node.id)) { @@ -297,58 +305,37 @@ export function VizTimeFilter() { ctx.fill(); }} /> + + + +

Trigger Event Cluster

+

Claim Cluster

+
+ + + +
+ +
+
-

Go Home

-

Details

- {selectedNode ? ( -
-

Title: {selectedNode.label}

-

Date: {new Date(selectedNode.avgDate).toISOString().slice(0, 10)}

- {selectedNode.members && ( -
-

Members:

-
    - {selectedNode.members.map((m) => { - const memberData = - data.claims.find((c) => c.id === m) || - data.events.find((e) => e.id === m); - - return ( -
  • - {memberData ? memberData.text : m} -
  • - ); - })} -
-
- )} -
- ) : ( -

Click a node to see details

- )} -
-
setInputDate(new Number(e.target.value))} - style={{ - width: "100%" - }} + className="w-full" /> -
- - {new Date(inputDate).toISOString().slice(0, 10)} (± 6 months window) - - -
+ + {new Date(inputDate).toISOString().slice(0, 10)} (± {filterLeeway} month(s) window) + +
); diff --git a/graphviz/frontend/src/utils/FloatingPanelStack.tsx b/graphviz/frontend/src/utils/FloatingPanelStack.tsx index 6a9c9d1..31d7e96 100644 --- a/graphviz/frontend/src/utils/FloatingPanelStack.tsx +++ b/graphviz/frontend/src/utils/FloatingPanelStack.tsx @@ -1,7 +1,8 @@ -export function FloatingPanelStack({ children }) { - return ( -
- {children} -
- ); +export function FloatingPanelStack({ children, bot = "sml" }) { + const botSty = bot == "sml" ? "bottom-4" : "bottom-20" + return ( +
+ {children} +
+ ); } \ No newline at end of file