Skip to content

Commit ac7ab22

Browse files
committed
Test
1 parent 58b1a14 commit ac7ab22

1 file changed

Lines changed: 156 additions & 119 deletions

File tree

src/components/GraphVisualizer.jsx

Lines changed: 156 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,181 @@
1-
import React, { useEffect, useState } from 'react';
2-
import { Card, Spin, Alert } from 'antd';
3-
import { useGraphStore } from '../store/graphStore';
1+
import React, { useCallback, useMemo } from "react";
2+
import { Card } from "antd";
3+
import ReactFlow, {
4+
Background,
5+
Controls,
6+
MiniMap,
7+
useNodesState,
8+
useEdgesState,
9+
addEdge,
10+
} from "reactflow";
11+
import "reactflow/dist/style.css";
12+
import { useGraphStore } from "../store/graphStore";
413

5-
export const GraphVisualizer = () => {
6-
const { nodes, edges, traversalState } = useGraphStore();
7-
const [graphImage, setGraphImage] = useState(null);
8-
const [loading, setLoading] = useState(false);
9-
const [error, setError] = useState(null);
14+
const nodeTypes = {};
1015

11-
const generateGraph = async () => {
12-
if (edges.length === 0) {
13-
setGraphImage(null);
14-
return;
15-
}
16+
export const GraphVisualizer = () => {
17+
const {
18+
nodes: storeNodes,
19+
edges: storeEdges,
20+
traversalState,
21+
} = useGraphStore();
1622

17-
setLoading(true);
18-
setError(null);
23+
const initialNodes = useMemo(() => {
24+
return storeNodes.map((node) => ({
25+
id: node.id,
26+
position: node.position,
27+
data: { label: node.data.label },
28+
style: {
29+
background: getNodeColor(node.id, traversalState),
30+
color: "#fff",
31+
border: "2px solid #222",
32+
borderRadius: "50%",
33+
width: 50,
34+
height: 50,
35+
display: "flex",
36+
alignItems: "center",
37+
justifyContent: "center",
38+
fontSize: "14px",
39+
fontWeight: "bold",
40+
transition: "all 0.3s ease",
41+
},
42+
type: "default",
43+
}));
44+
}, [storeNodes, traversalState]);
1945

20-
try {
21-
// Prepare data for Python backend
22-
const graphData = {
23-
edges: edges.map(edge => [edge.source, edge.target]),
24-
visited_nodes: Array.from(traversalState.visited),
25-
current_node: traversalState.current,
26-
current_edge: traversalState.currentEdge
27-
};
46+
const initialEdges = useMemo(() => {
47+
return storeEdges.map((edge) => ({
48+
id: edge.id,
49+
source: edge.source,
50+
target: edge.target,
51+
label: edge.label,
52+
type: 'straight',
53+
style: {
54+
stroke: getEdgeColor(edge, traversalState),
55+
strokeWidth: 2,
56+
transition: "all 0.3s ease",
57+
},
58+
labelStyle: {
59+
fontSize: 12,
60+
fontWeight: "bold",
61+
background: "#fff",
62+
padding: "2px 4px",
63+
borderRadius: "4px",
64+
},
65+
animated: isEdgeAnimated(edge, traversalState),
66+
}));
67+
}, [storeEdges, traversalState]);
2868

29-
const response = await fetch('http://localhost:5000/generate_graph', {
30-
method: 'POST',
31-
headers: {
32-
'Content-Type': 'application/json',
33-
},
34-
body: JSON.stringify(graphData)
35-
});
69+
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
70+
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
3671

37-
const result = await response.json();
72+
const onConnect = useCallback(
73+
(params) => setEdges((eds) => addEdge(params, eds)),
74+
[setEdges]
75+
);
3876

39-
if (result.success) {
40-
setGraphImage(result.image);
41-
} else {
42-
setError(result.error || 'Failed to generate graph');
43-
}
44-
} catch (err) {
45-
setError('Failed to connect to graph service. Make sure Python backend is running.');
46-
} finally {
47-
setLoading(false);
48-
}
49-
};
77+
// Update nodes and edges when store changes
78+
React.useEffect(() => {
79+
setNodes(initialNodes);
80+
}, [initialNodes, setNodes]);
5081

51-
useEffect(() => {
52-
generateGraph();
53-
}, [edges, traversalState.visited, traversalState.current, traversalState.currentEdge]);
82+
React.useEffect(() => {
83+
setEdges(initialEdges);
84+
}, [initialEdges, setEdges]);
5485

55-
if (nodes.length === 0) {
86+
if (storeNodes.length === 0) {
5687
return (
57-
<Card
58-
title="Graph Visualization"
59-
style={{
60-
borderRadius: '12px',
61-
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
62-
border: '1px solid #e8e8e8'
88+
<Card
89+
title="Graph Visualization"
90+
style={{
91+
borderRadius: "12px",
92+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
93+
border: "1px solid #e8e8e8",
6394
}}
6495
>
65-
<div style={{
66-
height: 400,
67-
display: 'flex',
68-
alignItems: 'center',
69-
justifyContent: 'center',
70-
background: '#f8fafc',
71-
borderRadius: '8px',
72-
color: '#64748b',
73-
fontSize: '16px',
74-
fontWeight: '500'
75-
}}>
96+
<div
97+
style={{
98+
height: 400,
99+
display: "flex",
100+
alignItems: "center",
101+
justifyContent: "center",
102+
background: "#f8fafc",
103+
borderRadius: "8px",
104+
color: "#64748b",
105+
fontSize: "16px",
106+
fontWeight: "500",
107+
}}
108+
>
76109
Please input a graph to visualize
77110
</div>
78111
</Card>
79112
);
80113
}
81114

82115
return (
83-
<Card
84-
title="Graph Visualization (Python Generated)"
85-
style={{
86-
borderRadius: '12px',
87-
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
88-
border: '1px solid #e8e8e8'
116+
<Card
117+
title="Interactive Graph Visualization"
118+
style={{
119+
borderRadius: "12px",
120+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
121+
border: "1px solid #e8e8e8",
89122
}}
90123
>
91-
<div style={{
92-
minHeight: 400,
93-
display: 'flex',
94-
alignItems: 'center',
95-
justifyContent: 'center',
96-
background: '#f8fafc',
97-
borderRadius: '8px',
98-
padding: '20px'
99-
}}>
100-
{loading && (
101-
<div style={{ textAlign: 'center' }}>
102-
<Spin size="large" />
103-
<div style={{ marginTop: '16px', color: '#64748b' }}>
104-
Generating beautiful graph...
105-
</div>
106-
</div>
107-
)}
108-
109-
{error && (
110-
<Alert
111-
message="Graph Generation Error"
112-
description={
113-
<div>
114-
<p>{error}</p>
115-
<p style={{ marginTop: '8px', fontSize: '12px' }}>
116-
To start the Python backend:
117-
<br />
118-
<code>pip install -r requirements.txt</code>
119-
<br />
120-
<code>python graph_generator.py</code>
121-
</p>
122-
</div>
123-
}
124-
type="error"
125-
showIcon
124+
<div style={{ height: 500, background: "#f8fafc", borderRadius: "8px" }}>
125+
<ReactFlow
126+
nodes={nodes}
127+
edges={edges}
128+
onNodesChange={onNodesChange}
129+
onEdgesChange={onEdgesChange}
130+
onConnect={onConnect}
131+
nodeTypes={nodeTypes}
132+
fitView
133+
attributionPosition="bottom-left"
134+
>
135+
<Background color="#aaa" gap={16} />
136+
<Controls />
137+
<MiniMap
138+
nodeColor={(node) => getNodeColor(node.id, traversalState)}
139+
nodeStrokeWidth={3}
140+
zoomable
141+
pannable
126142
/>
127-
)}
128-
129-
{graphImage && !loading && !error && (
130-
<img
131-
src={graphImage}
132-
alt="Graph Visualization"
133-
style={{
134-
maxWidth: '100%',
135-
maxHeight: '500px',
136-
borderRadius: '8px',
137-
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
138-
}}
139-
/>
140-
)}
143+
</ReactFlow>
141144
</div>
142145
</Card>
143146
);
144-
};
147+
};
148+
149+
function getNodeColor(nodeId, traversalState) {
150+
if (traversalState.current === nodeId) {
151+
return "#ff6b6b"; // Current node - red
152+
}
153+
if (traversalState.visited.has(nodeId)) {
154+
return "#51cf66"; // Visited node - green
155+
}
156+
return "#339af0"; // Unvisited node - blue
157+
}
158+
159+
function getEdgeColor(edge, traversalState) {
160+
// Current edge being traversed
161+
if (traversalState.currentEdge && traversalState.currentEdge === edge.id) {
162+
return "#ff6b6b"; // Current edge - red
163+
}
164+
165+
// Edge between visited nodes (traversed edge)
166+
if (traversalState.visited.has(edge.source) && traversalState.visited.has(edge.target)) {
167+
return "#51cf66"; // Traversed edge - green
168+
}
169+
170+
// Edge connected to current node
171+
if (traversalState.current &&
172+
(edge.source === traversalState.current || edge.target === traversalState.current)) {
173+
return "#ffd43b"; // Connected to current - yellow
174+
}
175+
176+
return "#b1b1b7"; // Default edge - gray
177+
}
178+
179+
function isEdgeAnimated(edge, traversalState) {
180+
return traversalState.currentEdge && traversalState.currentEdge === edge.id;
181+
}

0 commit comments

Comments
 (0)