Skip to content

Commit c84e8f1

Browse files
committed
style(ui): format graph visualization files
1 parent 587b90f commit c84e8f1

1 file changed

Lines changed: 85 additions & 84 deletions

File tree

frontend/src/components/graph/KnowledgeGraph.tsx

Lines changed: 85 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -230,91 +230,92 @@ export default function KnowledgeGraph({
230230
// ── Fetch graph data ────────────────────────────────────────────────────────
231231

232232
const fetchGraph = useCallback(async () => {
233-
setLoading(true);
234-
setError(null);
235-
setSelectedNode(null);
236-
237-
let data: GraphData | null = null;
238-
let fetchError: string | null = null;
239-
240-
try {
241-
data = await api.get<GraphData>(`/api/v1/graph/${documentId}`);
242-
} catch (err) {
243-
fetchError = err instanceof Error ? err.message : "Failed to load knowledge graph";
244-
}
245-
246-
// All setState calls happen after the await, satisfying the linter
247-
if (fetchError || !data) {
248-
setError(fetchError ?? "No data returned");
249-
setNodes([]);
250-
setEdges([]);
233+
setLoading(true);
234+
setError(null);
235+
setSelectedNode(null);
236+
237+
let data: GraphData | null = null;
238+
let fetchError: string | null = null;
239+
240+
try {
241+
data = await api.get<GraphData>(`/api/v1/graph/${documentId}`);
242+
} catch (err) {
243+
fetchError =
244+
err instanceof Error ? err.message : "Failed to load knowledge graph";
245+
}
246+
247+
// All setState calls happen after the await, satisfying the linter
248+
if (fetchError || !data) {
249+
setError(fetchError ?? "No data returned");
250+
setNodes([]);
251+
setEdges([]);
252+
setLoading(false);
253+
return;
254+
}
255+
256+
setGraphData(data);
257+
258+
const maxMentions = Math.max(...data.nodes.map((n) => n.mentions), 1);
259+
const radius = Math.min(Math.max(data.nodes.length * 18, 200), 500);
260+
261+
const rfNodes: Node[] = data.nodes.map((n, i) => {
262+
const colour = colourFor(n.label);
263+
const size = 36 + Math.round((n.mentions / maxMentions) * 36);
264+
const pos = radialPosition(i, data!.nodes.length, radius);
265+
return {
266+
id: n.id,
267+
position: pos,
268+
data: {
269+
label: (
270+
<div
271+
className="flex items-center justify-center text-center font-semibold leading-tight px-1"
272+
style={{ fontSize: Math.max(9, size * 0.22), color: colour.text }}
273+
title={n.name}
274+
>
275+
{n.name.length > 14 ? n.name.slice(0, 13) + "…" : n.name}
276+
</div>
277+
),
278+
_raw: n,
279+
},
280+
style: {
281+
width: size,
282+
height: size,
283+
borderRadius: "50%",
284+
backgroundColor: colour.bg,
285+
border: `2px solid ${colour.border}`,
286+
display: "flex",
287+
alignItems: "center",
288+
justifyContent: "center",
289+
cursor: "pointer",
290+
boxShadow: "0 1px 4px rgba(0,0,0,0.12)",
291+
},
292+
};
293+
});
294+
295+
const maxWeight = Math.max(...data.edges.map((e) => e.weight), 1);
296+
const rfEdges: Edge[] = data.edges.map((e, i) => {
297+
const opacity = 0.2 + 0.6 * (e.weight / maxWeight);
298+
const strokeWidth = 1 + Math.round((e.weight / maxWeight) * 3);
299+
return {
300+
id: `e-${i}`,
301+
source: e.source,
302+
target: e.target,
303+
animated: false,
304+
style: { stroke: `rgba(100,116,139,${opacity})`, strokeWidth },
305+
data: { _raw: e },
306+
};
307+
});
308+
309+
setNodes(rfNodes);
310+
setEdges(rfEdges);
251311
setLoading(false);
252-
return;
253-
}
254-
255-
setGraphData(data);
256-
257-
const maxMentions = Math.max(...data.nodes.map((n) => n.mentions), 1);
258-
const radius = Math.min(Math.max(data.nodes.length * 18, 200), 500);
259-
260-
const rfNodes: Node[] = data.nodes.map((n, i) => {
261-
const colour = colourFor(n.label);
262-
const size = 36 + Math.round((n.mentions / maxMentions) * 36);
263-
const pos = radialPosition(i, data!.nodes.length, radius);
264-
return {
265-
id: n.id,
266-
position: pos,
267-
data: {
268-
label: (
269-
<div
270-
className="flex items-center justify-center text-center font-semibold leading-tight px-1"
271-
style={{ fontSize: Math.max(9, size * 0.22), color: colour.text }}
272-
title={n.name}
273-
>
274-
{n.name.length > 14 ? n.name.slice(0, 13) + "…" : n.name}
275-
</div>
276-
),
277-
_raw: n,
278-
},
279-
style: {
280-
width: size,
281-
height: size,
282-
borderRadius: "50%",
283-
backgroundColor: colour.bg,
284-
border: `2px solid ${colour.border}`,
285-
display: "flex",
286-
alignItems: "center",
287-
justifyContent: "center",
288-
cursor: "pointer",
289-
boxShadow: "0 1px 4px rgba(0,0,0,0.12)",
290-
},
291-
};
292-
});
293-
294-
const maxWeight = Math.max(...data.edges.map((e) => e.weight), 1);
295-
const rfEdges: Edge[] = data.edges.map((e, i) => {
296-
const opacity = 0.2 + 0.6 * (e.weight / maxWeight);
297-
const strokeWidth = 1 + Math.round((e.weight / maxWeight) * 3);
298-
return {
299-
id: `e-${i}`,
300-
source: e.source,
301-
target: e.target,
302-
animated: false,
303-
style: { stroke: `rgba(100,116,139,${opacity})`, strokeWidth },
304-
data: { _raw: e },
305-
};
306-
});
307-
308-
setNodes(rfNodes);
309-
setEdges(rfEdges);
310-
setLoading(false);
311-
}, [documentId, setNodes, setEdges]);
312-
313-
useEffect(() => {
314-
fetchGraph();
315-
// fetchGraph is stable (memoised on documentId) — safe to omit from deps
316-
// eslint-disable-next-line react-hooks/exhaustive-deps
317-
}, [documentId]);
312+
}, [documentId, setNodes, setEdges]);
313+
314+
useEffect(() => {
315+
fetchGraph();
316+
// fetchGraph is stable (memoised on documentId) — safe to omit from deps
317+
// eslint-disable-next-line react-hooks/exhaustive-deps
318+
}, [documentId]);
318319

319320
// ── Node click → show detail panel ─────────────────────────────────────────
320321

0 commit comments

Comments
 (0)