import { useState, useCallback, ReactNode } from 'react'; import { ReactFlow, applyNodeChanges, applyEdgeChanges, addEdge, Background, Controls, ReactFlowProvider, NodeTypes, NodeChange, OnEdgesChange, MarkerType, OnConnect, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import { AppNode, AppEdge, NodeData } from './types/graph'; import CustomNode from './components/CustomNode'; import NodeEditor from './components/NodeEditor'; import ConfigViewer from './components/ConfigViewer'; import Toggle from "./components/Toggle" import './App.css'; const initialNodes: AppNode[] = [ { id: 'n1', position: { x: 250, y: 50 }, data: { label: 'Node-A', ipAddress: '10.0.0.1', listenPort: '51820', privateKey: '', publicKey: '', }, type: 'custom', }, ]; const initialEdges: AppEdge[] = []; const nodeTypes : NodeTypes = { custom: CustomNode, }; function FlowContent(): ReactNode { const [nodes, setNodes] = useState(initialNodes); const [edges, setEdges] = useState(initialEdges); const [editingNode, setEditingNode] = useState(null); const [showConfigViewer, setShowConfigViewer] = useState(false); const onNodesChange = useCallback( (changes: NodeChange[]) => setNodes((nds) => applyNodeChanges(changes, nds)), [], ); const onEdgesChange = useCallback( (changes) => setEdges((edgesSnapshot) => applyEdgeChanges(changes, edgesSnapshot)), [], ); const onConnect = useCallback( (params) => setEdges((edgesSnapshot) => addEdge(params, edgesSnapshot)), [], ); const onNodeClick = useCallback((_event: React.MouseEvent, node: AppNode) => { setEditingNode(node.data); }, []); const handleAddNode = (): void => { const newNodeId = `n${Date.now()}`; const newNode: AppNode = { id: newNodeId, position: { x: Math.random() * 500, y: Math.random() * 500 }, data: { label: `Node-${String.fromCharCode(65 + (nodes.length % 26))}`, ipAddress: `10.0.0.${nodes.length + 2}`, listenPort: `${51820 + nodes.length}`, privateKey: '', publicKey: '', }, type: 'custom', }; setNodes((prev) => [...prev, newNode]); }; const handleUpdateNode = (updatedData: NodeData): void => { setNodes((prev) => prev.map((node) => { if (node.data.label === editingNode?.label) { return { ...node, data: updatedData }; } return node; }) ); setEditingNode(null); }; return (
{editingNode && ( setEditingNode(null)} /> )} {showConfigViewer && ( setShowConfigViewer(false)} /> )}
); } export default function App(): ReactNode { return ( ); }