diff --git a/backend/diagrams/diagram_argo.json b/backend/diagrams/diagram_argo.json
deleted file mode 100644
index 184c8c0..0000000
--- a/backend/diagrams/diagram_argo.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "nodes": [
- {
- "id": "1",
- "type": "custom",
- "data": {
- "label": "Node 1",
- "icon": "https://s3.dvirlabs.com/lab-icons/dev-tools/argocd.svg"
- },
- "position": {
- "x": 307.58165778037267,
- "y": 195.1586839847007
- },
- "width": 103,
- "height": 103
- }
- ],
- "edges": []
-}
\ No newline at end of file
diff --git a/frontend/src/components/ColorNode.jsx b/frontend/src/components/ColorNode.jsx
deleted file mode 100644
index 8eafab3..0000000
--- a/frontend/src/components/ColorNode.jsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Handle, Position } from 'reactflow';
-
-function ColorNode({ data }) {
- return (
-
-
-
🎨 Shape Color
-
data.onChange?.(e.target.value)}
- style={{ width: '100%' }}
- />
-
-
- );
-}
-
-export default ColorNode;
diff --git a/frontend/src/components/Diagram.jsx b/frontend/src/components/Diagram.jsx
index a5c1165..51074fb 100644
--- a/frontend/src/components/Diagram.jsx
+++ b/frontend/src/components/Diagram.jsx
@@ -17,42 +17,34 @@ import CustomNode from './CustomNode';
import IconSelector from './IconSelector';
import { toast } from 'react-toastify';
import RouterNode from './RouterNode';
-import ColorNode from './ColorNode';
-
const nodeTypes = {
custom: CustomNode,
router: RouterNode,
- color: ColorNode,
};
function Diagram() {
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const [selectedNode, setSelectedNode] = useState(null);
+ const [selectedEdge, setSelectedEdge] = useState(null);
const [showForm, setShowForm] = useState(false);
const [newLabel, setNewLabel] = useState('');
const [newType, setNewType] = useState('custom');
const [selectedIcon, setSelectedIcon] = useState('');
- const [selectedEdge, setSelectedEdge] = useState(null);
const [diagramName, setDiagramName] = useState(null);
const [diagramList, setDiagramList] = useState([]);
const isIframe = window.self !== window.top;
useEffect(() => {
- let isMounted = true;
-
const load = async () => {
try {
const { diagrams } = await listDiagrams();
- if (isMounted) {
- setDiagramList(diagrams);
-
- if (diagrams.length > 0) {
- setDiagramName((prev) => prev || diagrams[0]);
- } else {
- setDiagramName(null);
- }
+ setDiagramList(diagrams);
+ if (diagrams.length > 0) {
+ setDiagramName((prev) => prev || diagrams[0]);
+ } else {
+ setDiagramName(null);
}
} catch (err) {
console.error(err);
@@ -60,16 +52,10 @@ function Diagram() {
setDiagramName(null);
}
};
-
load();
- return () => {
- isMounted = false;
- };
}, []);
useEffect(() => {
- let isMounted = true;
-
const loadDiagram = async () => {
if (!diagramName) {
setNodes([]);
@@ -78,18 +64,13 @@ function Diagram() {
}
try {
const data = await fetchDiagramByName(diagramName);
- if (isMounted) {
- setNodes(data.nodes || []);
- const sanitizedEdges = (data.edges || []).map(({ id, source, target, animated }) => ({
- id,
- source,
- target,
- animated: !!animated,
- }));
- setEdges(sanitizedEdges);
- setSelectedNode(null);
- setSelectedEdge(null);
- }
+ setNodes(data.nodes || []);
+ const sanitizedEdges = (data.edges || []).map(({ id, source, target, animated }) => ({
+ id, source, target, animated: !!animated
+ }));
+ setEdges(sanitizedEdges);
+ setSelectedNode(null);
+ setSelectedEdge(null);
} catch (err) {
console.error(err);
toast.error(`❌ Failed to load diagram "${diagramName}"`);
@@ -97,29 +78,18 @@ function Diagram() {
setEdges([]);
}
};
-
loadDiagram();
- return () => {
- isMounted = false;
- };
- }, [diagramName, setNodes, setEdges]);
+ }, [diagramName]);
const handleSave = async () => {
if (!diagramName) return;
const cleanedEdges = edges.map(({ id, source, target, animated }) => ({
- id,
- source,
- target,
- animated: !!animated,
+ id, source, target, animated: !!animated
}));
await saveDiagramByName(diagramName, { nodes, edges: cleanedEdges });
toast.success(`✅ Diagram "${diagramName}" saved!`);
};
- const handleAddNode = () => {
- setShowForm(true);
- };
-
const handleSubmitNode = () => {
const id = (nodes.length + 1).toString();
const label = newLabel || `Node ${id}`;
@@ -128,9 +98,7 @@ function Diagram() {
const newNode = {
id,
type: newType,
- data: newType === 'custom'
- ? { label, icon }
- : { label }, // router and other types don't have icons
+ data: newType === 'custom' ? { label, icon } : { label },
position: { x: Math.random() * 400, y: Math.random() * 300 },
};
@@ -150,6 +118,11 @@ function Diagram() {
setSelectedNode(null);
};
+ const onConnect = useCallback(
+ (params) => setEdges((eds) => addEdge({ ...params, animated: true }, eds)),
+ [setEdges]
+ );
+
const onEdgeClick = (_, edge) => {
setSelectedEdge(edge);
setSelectedNode(null);
@@ -162,12 +135,9 @@ function Diagram() {
setSelectedEdge(null);
};
- const onConnect = useCallback(
- (params) => setEdges((eds) => addEdge({ ...params, animated: true }, eds)),
- [setEdges]
- );
+ const onNodeClick = (_, node) => setSelectedNode(node);
- const handleNodeDoubleClick = (event, node) => {
+ const handleNodeDoubleClick = (_, node) => {
const newLabel = prompt('Enter new name:', node.data.label);
if (newLabel !== null) {
setNodes((nds) =>
@@ -179,19 +149,12 @@ function Diagram() {
}
};
- const onNodeClick = (_, node) => {
- setSelectedNode(node);
- };
-
const handleDeleteDiagram = async () => {
if (!diagramName || diagramName === 'default') {
toast.warn("❌ Cannot delete 'default' diagram or nothing selected.");
return;
}
-
- const confirmDelete = confirm(`Are you sure you want to delete diagram "${diagramName}"?`);
- if (!confirmDelete) return;
-
+ if (!confirm(`Delete "${diagramName}"?`)) return;
try {
await deleteDiagramByName(diagramName);
const updatedList = diagramList.filter(name => name !== diagramName);
@@ -208,8 +171,8 @@ function Diagram() {
return (
-
-
+
+
-
@@ -255,43 +208,36 @@ function Diagram() {
const newName = prompt("Enter new diagram name:");
if (newName) {
if (!diagramList.includes(newName)) {
- const updatedList = [...diagramList, newName];
- setDiagramList(updatedList);
+ setDiagramList((prev) => [...prev, newName]);
}
setDiagramName(newName);
setNodes([]);
setEdges([]);
- setSelectedNode(null);
- setSelectedEdge(null);
}
}}>🆕 New Diagram
-
-
-
-
-
-
+
+
+
>
)}
{showForm && (
-
-
🧩 Add New Node
+
+
🧩 Add New Node
-
+
setNewLabel(e.target.value)}
style={{ padding: '6px', width: '100%', borderRadius: 6, border: '1px solid #ccc', marginBottom: 12 }}
/>
-
+
- {newType === 'custom' && (
-
- )}
+ {newType === 'custom' &&
}
diff --git a/frontend/src/components/IconSelector.jsx b/frontend/src/components/IconSelector.jsx
index 24a9b3e..845b909 100644
--- a/frontend/src/components/IconSelector.jsx
+++ b/frontend/src/components/IconSelector.jsx
@@ -25,7 +25,7 @@ function IconSelector({ onSelect }) {
return (
-
+