Spaces:
Running
Running
Update static/canvas.js
Browse files- static/canvas.js +136 -20
static/canvas.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
// Initialize Konva stage
|
2 |
const stage = new Konva.Stage({
|
3 |
container: 'container',
|
4 |
-
width:
|
5 |
height: 600
|
6 |
});
|
7 |
|
@@ -13,27 +13,105 @@ let nodes = [];
|
|
13 |
let connections = [];
|
14 |
let selectedNode = null;
|
15 |
|
16 |
-
//
|
17 |
-
function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
const node = new Konva.Group({
|
19 |
-
x:
|
20 |
-
y:
|
21 |
draggable: true
|
22 |
});
|
23 |
|
24 |
// Node rectangle
|
|
|
25 |
const box = new Konva.Rect({
|
26 |
width: 100,
|
27 |
height: 50,
|
28 |
-
fill:
|
29 |
stroke: 'black',
|
30 |
strokeWidth: 2,
|
31 |
cornerRadius: 5
|
32 |
});
|
33 |
|
34 |
-
// Node
|
35 |
const text = new Konva.Text({
|
36 |
-
text:
|
37 |
fontSize: 12,
|
38 |
fontFamily: 'Arial',
|
39 |
fill: 'black',
|
@@ -45,29 +123,52 @@ function addNode() {
|
|
45 |
node.add(box);
|
46 |
node.add(text);
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
// Node data
|
49 |
node.data = {
|
50 |
-
id:
|
51 |
-
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
54 |
};
|
55 |
|
56 |
-
// Handle node click for connections
|
57 |
node.on('click', () => {
|
58 |
if (!selectedNode) {
|
59 |
selectedNode = node;
|
60 |
} else {
|
61 |
-
// Create connection
|
62 |
const line = new Konva.Line({
|
63 |
points: [
|
64 |
-
selectedNode.x() +
|
65 |
-
node.x()
|
66 |
],
|
67 |
stroke: 'black',
|
68 |
strokeWidth: 2
|
69 |
});
|
70 |
-
|
71 |
connections.push({
|
72 |
from: selectedNode.data.id,
|
73 |
to: node.data.id
|
@@ -77,7 +178,7 @@ function addNode() {
|
|
77 |
}
|
78 |
});
|
79 |
|
80 |
-
// Update position on drag
|
81 |
node.on('dragmove', () => {
|
82 |
node.data.x = node.x();
|
83 |
node.data.y = node.y();
|
@@ -85,9 +186,24 @@ function addNode() {
|
|
85 |
saveNodes();
|
86 |
});
|
87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
nodes.push(node);
|
89 |
layer.add(node);
|
90 |
layer.draw();
|
|
|
91 |
}
|
92 |
|
93 |
// Update connection lines when nodes move
|
@@ -99,8 +215,8 @@ function updateConnections() {
|
|
99 |
const line = layer.find('Line')[index];
|
100 |
if (line) {
|
101 |
line.points([
|
102 |
-
fromNode.x() +
|
103 |
-
toNode.x()
|
104 |
]);
|
105 |
}
|
106 |
}
|
|
|
1 |
// Initialize Konva stage
|
2 |
const stage = new Konva.Stage({
|
3 |
container: 'container',
|
4 |
+
width: 1000,
|
5 |
height: 600
|
6 |
});
|
7 |
|
|
|
13 |
let connections = [];
|
14 |
let selectedNode = null;
|
15 |
|
16 |
+
// Submit code or file for parsing
|
17 |
+
function submitCode() {
|
18 |
+
const fileInput = document.getElementById('codeFile');
|
19 |
+
const codeInput = document.getElementById('codeInput').value;
|
20 |
+
const formData = new FormData();
|
21 |
+
|
22 |
+
if (fileInput.files.length > 0) {
|
23 |
+
formData.append('file', fileInput.files[0]);
|
24 |
+
} else if (codeInput) {
|
25 |
+
formData.append('code', codeInput);
|
26 |
+
} else {
|
27 |
+
alert('Please upload a file or paste code.');
|
28 |
+
return;
|
29 |
+
}
|
30 |
+
|
31 |
+
fetch('/parse_code', {
|
32 |
+
method: 'POST',
|
33 |
+
body: formData
|
34 |
+
})
|
35 |
+
.then(response => response.json())
|
36 |
+
.then(data => {
|
37 |
+
if (data.error) {
|
38 |
+
alert(data.error);
|
39 |
+
return;
|
40 |
+
}
|
41 |
+
clearCanvas();
|
42 |
+
createNodesFromParsedData(data.nodes, data.connections);
|
43 |
+
})
|
44 |
+
.catch(error => console.error('Error:', error));
|
45 |
+
}
|
46 |
+
|
47 |
+
// Clear existing nodes and connections
|
48 |
+
function clearCanvas() {
|
49 |
+
nodes.forEach(node => node.destroy());
|
50 |
+
layer.find('Line').forEach(line => line.destroy());
|
51 |
+
nodes = [];
|
52 |
+
connections = [];
|
53 |
+
layer.draw();
|
54 |
+
}
|
55 |
+
|
56 |
+
// Create nodes and connections from parsed data
|
57 |
+
function createNodesFromParsedData(parsedNodes, parsedConnections) {
|
58 |
+
parsedNodes.forEach(nodeData => {
|
59 |
+
const node = createNode(
|
60 |
+
nodeData.x,
|
61 |
+
nodeData.y,
|
62 |
+
nodeData.label,
|
63 |
+
nodeData.type,
|
64 |
+
nodeData.inputs,
|
65 |
+
nodeData.outputs,
|
66 |
+
nodeData.id
|
67 |
+
);
|
68 |
+
nodes.push(node);
|
69 |
+
layer.add(node);
|
70 |
+
});
|
71 |
+
|
72 |
+
parsedConnections.forEach(conn => {
|
73 |
+
const fromNode = nodes.find(n => n.data.id === conn.from);
|
74 |
+
const toNode = nodes.find(n => n.data.id === conn.to);
|
75 |
+
if (fromNode && toNode) {
|
76 |
+
const line = new Konva.Line({
|
77 |
+
points: [
|
78 |
+
fromNode.x() + 100, fromNode.y() + 25,
|
79 |
+
toNode.x(), toNode.y() + 25
|
80 |
+
],
|
81 |
+
stroke: 'black',
|
82 |
+
strokeWidth: 2
|
83 |
+
});
|
84 |
+
layer.add(line);
|
85 |
+
connections.push({ from: conn.from, to: conn.to });
|
86 |
+
}
|
87 |
+
});
|
88 |
+
|
89 |
+
layer.draw();
|
90 |
+
saveNodes();
|
91 |
+
}
|
92 |
+
|
93 |
+
// Create a node with inputs and outputs
|
94 |
+
function createNode(x, y, label, type, inputs = [], outputs = [], id) {
|
95 |
const node = new Konva.Group({
|
96 |
+
x: x,
|
97 |
+
y: y,
|
98 |
draggable: true
|
99 |
});
|
100 |
|
101 |
// Node rectangle
|
102 |
+
const color = type === 'function' ? '#ffeb3b' : type.includes('variable') ? '#90caf9' : '#ccc';
|
103 |
const box = new Konva.Rect({
|
104 |
width: 100,
|
105 |
height: 50,
|
106 |
+
fill: color,
|
107 |
stroke: 'black',
|
108 |
strokeWidth: 2,
|
109 |
cornerRadius: 5
|
110 |
});
|
111 |
|
112 |
+
// Node label
|
113 |
const text = new Konva.Text({
|
114 |
+
text: label,
|
115 |
fontSize: 12,
|
116 |
fontFamily: 'Arial',
|
117 |
fill: 'black',
|
|
|
123 |
node.add(box);
|
124 |
node.add(text);
|
125 |
|
126 |
+
// Add input/output ports
|
127 |
+
inputs.forEach((input, i) => {
|
128 |
+
const circle = new Konva.Circle({
|
129 |
+
x: 0,
|
130 |
+
y: 10 + i * 20,
|
131 |
+
radius: 5,
|
132 |
+
fill: 'red'
|
133 |
+
});
|
134 |
+
node.add(circle);
|
135 |
+
});
|
136 |
+
|
137 |
+
outputs.forEach((output, i) => {
|
138 |
+
const circle = new Konva.Circle({
|
139 |
+
x: 100,
|
140 |
+
y: 10 + i * 20,
|
141 |
+
radius: 5,
|
142 |
+
fill: 'green'
|
143 |
+
});
|
144 |
+
node.add(circle);
|
145 |
+
});
|
146 |
+
|
147 |
// Node data
|
148 |
node.data = {
|
149 |
+
id: id,
|
150 |
+
type: type,
|
151 |
+
label: label,
|
152 |
+
inputs: inputs,
|
153 |
+
outputs: outputs,
|
154 |
+
x: x,
|
155 |
+
y: y
|
156 |
};
|
157 |
|
158 |
+
// Handle node click for manual connections
|
159 |
node.on('click', () => {
|
160 |
if (!selectedNode) {
|
161 |
selectedNode = node;
|
162 |
} else {
|
|
|
163 |
const line = new Konva.Line({
|
164 |
points: [
|
165 |
+
selectedNode.x() + 100, selectedNode.y() + 25,
|
166 |
+
node.x(), node.y() + 25
|
167 |
],
|
168 |
stroke: 'black',
|
169 |
strokeWidth: 2
|
170 |
});
|
171 |
+
layer.add(line);
|
172 |
connections.push({
|
173 |
from: selectedNode.data.id,
|
174 |
to: node.data.id
|
|
|
178 |
}
|
179 |
});
|
180 |
|
181 |
+
// Update position and connections on drag
|
182 |
node.on('dragmove', () => {
|
183 |
node.data.x = node.x();
|
184 |
node.data.y = node.y();
|
|
|
186 |
saveNodes();
|
187 |
});
|
188 |
|
189 |
+
return node;
|
190 |
+
}
|
191 |
+
|
192 |
+
// Add a manual node
|
193 |
+
function addNode() {
|
194 |
+
const node = createNode(
|
195 |
+
Math.random() * (stage.width() - 100),
|
196 |
+
Math.random() * (stage.height() - 100),
|
197 |
+
'Function',
|
198 |
+
'function',
|
199 |
+
[],
|
200 |
+
[],
|
201 |
+
nodes.length
|
202 |
+
);
|
203 |
nodes.push(node);
|
204 |
layer.add(node);
|
205 |
layer.draw();
|
206 |
+
saveNodes();
|
207 |
}
|
208 |
|
209 |
// Update connection lines when nodes move
|
|
|
215 |
const line = layer.find('Line')[index];
|
216 |
if (line) {
|
217 |
line.points([
|
218 |
+
fromNode.x() + 100, fromNode.y() + 25,
|
219 |
+
toNode.x(), toNode.y() + 25
|
220 |
]);
|
221 |
}
|
222 |
}
|