// Initialize Konva stage const stage = new Konva.Stage({ container: 'container', width: 1000, height: 600 }); const layer = new Konva.Layer(); stage.add(layer); // Store nodes and connections let nodes = []; let connections = []; let selectedNode = null; // Submit code or file for parsing function submitCode() { const fileInput = document.getElementById('codeFile'); const codeInput = document.getElementById('codeInput').value; const formData = new FormData(); if (fileInput.files.length > 0) { formData.append('file', fileInput.files[0]); } else if (codeInput) { formData.append('code', codeInput); } else { alert('Please upload a file or paste code.'); return; } fetch('/parse_code', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if (data.error) { alert(data.error); return; } clearCanvas(); createNodesFromParsedData(data.nodes, data.connections); }) .catch(error => console.error('Error:', error)); } // Clear existing nodes and connections function clearCanvas() { nodes.forEach(node => node.destroy()); layer.find('Line').forEach(line => line.destroy()); nodes = []; connections = []; layer.draw(); } // Create nodes and connections from parsed data function createNodesFromParsedData(parsedNodes, parsedConnections) { parsedNodes.forEach(nodeData => { const node = createNode( nodeData.x, nodeData.y, nodeData.label, nodeData.type, nodeData.inputs, nodeData.outputs, nodeData.id ); nodes.push(node); layer.add(node); }); parsedConnections.forEach(conn => { const fromNode = nodes.find(n => n.data.id === conn.from); const toNode = nodes.find(n => n.data.id === conn.to); if (fromNode && toNode) { const line = new Konva.Line({ points: [ fromNode.x() + 100, fromNode.y() + 25, toNode.x(), toNode.y() + 25 ], stroke: 'black', strokeWidth: 2 }); layer.add(line); connections.push({ from: conn.from, to: conn.to }); } }); layer.draw(); saveNodes(); } // Create a node with inputs and outputs function createNode(x, y, label, type, inputs = [], outputs = [], id) { const node = new Konva.Group({ x: x, y: y, draggable: true }); // Node rectangle const color = type === 'function' ? '#ffeb3b' : type.includes('variable') ? '#90caf9' : '#ccc'; const box = new Konva.Rect({ width: 100, height: 50, fill: color, stroke: 'black', strokeWidth: 2, cornerRadius: 5 }); // Node label const text = new Konva.Text({ text: label, fontSize: 12, fontFamily: 'Arial', fill: 'black', width: 100, align: 'center', y: 20 }); node.add(box); node.add(text); // Add input/output ports inputs.forEach((input, i) => { const circle = new Konva.Circle({ x: 0, y: 10 + i * 20, radius: 5, fill: 'red' }); node.add(circle); }); outputs.forEach((output, i) => { const circle = new Konva.Circle({ x: 100, y: 10 + i * 20, radius: 5, fill: 'green' }); node.add(circle); }); // Node data node.data = { id: id, type: type, label: label, inputs: inputs, outputs: outputs, x: x, y: y }; // Handle node click for manual connections node.on('click', () => { if (!selectedNode) { selectedNode = node; } else { const line = new Konva.Line({ points: [ selectedNode.x() + 100, selectedNode.y() + 25, node.x(), node.y() + 25 ], stroke: 'black', strokeWidth: 2 }); layer.add(line); connections.push({ from: selectedNode.data.id, to: node.data.id }); selectedNode = null; saveNodes(); } }); // Update position and connections on drag node.on('dragmove', () => { node.data.x = node.x(); node.data.y = node.y(); updateConnections(); saveNodes(); }); return node; } // Add a manual node function addNode() { const node = createNode( Math.random() * (stage.width() - 100), Math.random() * (stage.height() - 100), 'Function', 'function', [], [], nodes.length ); nodes.push(node); layer.add(node); layer.draw(); saveNodes(); } // Update connection lines when nodes move function updateConnections() { connections.forEach((conn, index) => { const fromNode = nodes.find(n => n.data.id === conn.from); const toNode = nodes.find(n => n.data.id === conn.to); if (fromNode && toNode) { const line = layer.find('Line')[index]; if (line) { line.points([ fromNode.x() + 100, fromNode.y() + 25, toNode.x(), toNode.y() + 25 ]); } } }); layer.draw(); } // Save nodes and connections to backend function saveNodes() { fetch('/save_nodes', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nodes: nodes.map(n => n.data), connections: connections }) }).then(response => response.json()) .then(data => console.log('Saved:', data)) .catch(error => console.error('Error:', error)); } // Initial draw layer.draw();