@linkdlab/funcnodes_react_flow 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -0
- package/package copy.json +63 -0
- package/package.json +75 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +43 -0
- package/public/logo192.png +0 -0
- package/public/logo512.png +0 -0
- package/public/manifest.json +25 -0
- package/public/robots.txt +3 -0
- package/public/worker_manager +1 -0
- package/src/App.css +38 -0
- package/src/App.test.tsx +9 -0
- package/src/App.tsx +22 -0
- package/src/frontend/datarenderer/images.tsx +28 -0
- package/src/frontend/datarenderer/index.tsx +53 -0
- package/src/frontend/datarenderer/plotly.tsx +82 -0
- package/src/frontend/dialog.scss +88 -0
- package/src/frontend/dialog.tsx +70 -0
- package/src/frontend/edge.scss +15 -0
- package/src/frontend/edge.tsx +31 -0
- package/src/frontend/funcnodesreactflow.scss +63 -0
- package/src/frontend/funcnodesreactflow.tsx +283 -0
- package/src/frontend/header/header.scss +48 -0
- package/src/frontend/header/index.tsx +268 -0
- package/src/frontend/index.tsx +4 -0
- package/src/frontend/layout/htmlelements.scss +63 -0
- package/src/frontend/lib.scss +157 -0
- package/src/frontend/lib.tsx +198 -0
- package/src/frontend/node/index.tsx +3 -0
- package/src/frontend/node/io/default_input_renderer.tsx +327 -0
- package/src/frontend/node/io/default_output_render.tsx +26 -0
- package/src/frontend/node/io/handle_renderer.tsx +89 -0
- package/src/frontend/node/io/index.tsx +4 -0
- package/src/frontend/node/io/io.scss +91 -0
- package/src/frontend/node/io/io.tsx +114 -0
- package/src/frontend/node/io/nodeinput.tsx +125 -0
- package/src/frontend/node/io/nodeoutput.tsx +37 -0
- package/src/frontend/node/node.scss +265 -0
- package/src/frontend/node/node.tsx +208 -0
- package/src/frontend/nodecontextmenu.scss +18 -0
- package/src/frontend/utils/colorpicker.scss +37 -0
- package/src/frontend/utils/colorpicker.tsx +342 -0
- package/src/frontend/utils/jsondata.tsx +19 -0
- package/src/frontend/utils/table.scss +22 -0
- package/src/frontend/utils/table.tsx +159 -0
- package/src/funcnodes/funcnodesworker.ts +455 -0
- package/src/funcnodes/index.ts +4 -0
- package/src/funcnodes/websocketworker.ts +153 -0
- package/src/funcnodes/workermanager.ts +229 -0
- package/src/index.css +13 -0
- package/src/index.tsx +19 -0
- package/src/logo.svg +1 -0
- package/src/react-app-env.d.ts +1 -0
- package/src/reportWebVitals.ts +15 -0
- package/src/setupTests.ts +5 -0
- package/src/state/edge.ts +35 -0
- package/src/state/fnrfzst.ts +440 -0
- package/src/state/index.ts +139 -0
- package/src/state/lib.ts +26 -0
- package/src/state/node.ts +118 -0
- package/src/state/nodespace.ts +151 -0
- package/src/state/reactflow.ts +65 -0
- package/src/types/lib.d.ts +16 -0
- package/src/types/node.d.ts +29 -0
- package/src/types/nodeio.d.ts +82 -0
- package/src/types/worker.d.ts +56 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { FuncNodesReactFlowZustandInterface, WorkersState } from "../state";
|
|
2
|
+
import FuncNodesWorker from "./funcnodesworker";
|
|
3
|
+
import WebSocketWorker from "./websocketworker";
|
|
4
|
+
|
|
5
|
+
class WorkerManager {
|
|
6
|
+
private wsuri: string;
|
|
7
|
+
private workers: any;
|
|
8
|
+
private ws: WebSocket | null = null;
|
|
9
|
+
private reconnectAttempts: number = 0;
|
|
10
|
+
private maxReconnectAttempts: number = 999;
|
|
11
|
+
private initialTimeout: number = 200; // Initial reconnect delay in ms
|
|
12
|
+
private maxTimeout: number = 2000; // Maximum reconnect delay
|
|
13
|
+
private zustand: FuncNodesReactFlowZustandInterface;
|
|
14
|
+
private connectionTimeout?: NodeJS.Timeout;
|
|
15
|
+
on_setWorker: (worker: FuncNodesWorker | undefined) => void;
|
|
16
|
+
constructor(wsuri: string, zustand: FuncNodesReactFlowZustandInterface) {
|
|
17
|
+
this.wsuri = wsuri;
|
|
18
|
+
this.zustand = zustand;
|
|
19
|
+
this.workers = {};
|
|
20
|
+
this.on_setWorker = (worker: FuncNodesWorker | undefined) => {
|
|
21
|
+
console.log("WorkerManager: on_setWorker", worker);
|
|
22
|
+
this.zustand.worker = worker;
|
|
23
|
+
};
|
|
24
|
+
this.connect();
|
|
25
|
+
}
|
|
26
|
+
private connect(): void {
|
|
27
|
+
this.zustand.set_progress({
|
|
28
|
+
progress: 0,
|
|
29
|
+
message: "connecting to worker manager",
|
|
30
|
+
status: "info",
|
|
31
|
+
blocking: true,
|
|
32
|
+
});
|
|
33
|
+
console.log("Connecting to websocket");
|
|
34
|
+
this.ws = new WebSocket(this.wsuri);
|
|
35
|
+
|
|
36
|
+
this.ws.onopen = () => {
|
|
37
|
+
this.onopen();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
this.ws.onclose = () => {
|
|
41
|
+
this.onclose();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
this.ws.onerror = () => {
|
|
45
|
+
this.on_ws_error();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
this.ws.onmessage = (event) => {
|
|
49
|
+
this.onmessage(event.data);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
this.connectionTimeout = setTimeout(() => {
|
|
53
|
+
if (this.ws?.readyState !== WebSocket.OPEN) {
|
|
54
|
+
this.on_ws_error();
|
|
55
|
+
}
|
|
56
|
+
}, 5000);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
on_ws_error() {
|
|
60
|
+
console.warn("Websocket error");
|
|
61
|
+
if (this.ws) {
|
|
62
|
+
this.ws.close(); // Ensure the connection is closed before attempting to reconnect
|
|
63
|
+
} else {
|
|
64
|
+
this.reconnect();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
onopen() {
|
|
69
|
+
if (this.connectionTimeout) {
|
|
70
|
+
clearTimeout(this.connectionTimeout);
|
|
71
|
+
this.connectionTimeout = undefined;
|
|
72
|
+
}
|
|
73
|
+
this.zustand.auto_progress();
|
|
74
|
+
console.log("WorkerManager: onopen");
|
|
75
|
+
if (this.ws) {
|
|
76
|
+
this.ws.send("worker_status");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Get active worker from window storage
|
|
80
|
+
const active_worker = window.localStorage.getItem(
|
|
81
|
+
"funcnodes__active_worker"
|
|
82
|
+
);
|
|
83
|
+
if (active_worker) {
|
|
84
|
+
this.set_active(active_worker);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
onmessage(event: string) {
|
|
88
|
+
let msg = JSON.parse(event);
|
|
89
|
+
if (msg.type === "worker_status") {
|
|
90
|
+
console.debug("WorkerManager: worker_status", msg);
|
|
91
|
+
const new_state: WorkersState = {};
|
|
92
|
+
for (let worker of msg.active) {
|
|
93
|
+
worker.active = true;
|
|
94
|
+
new_state[worker.uuid] = worker;
|
|
95
|
+
}
|
|
96
|
+
for (let worker of msg.inactive) {
|
|
97
|
+
worker.active = false;
|
|
98
|
+
new_state[worker.uuid] = worker;
|
|
99
|
+
}
|
|
100
|
+
this.zustand.workers.setState(new_state);
|
|
101
|
+
return;
|
|
102
|
+
} else if (msg.type === "set_worker") {
|
|
103
|
+
if (msg.data.type === "WSWorker") {
|
|
104
|
+
let url =
|
|
105
|
+
"ws" +
|
|
106
|
+
(msg.data.ssl ? "s" : "") +
|
|
107
|
+
"://" +
|
|
108
|
+
msg.data.host +
|
|
109
|
+
":" +
|
|
110
|
+
msg.data.port;
|
|
111
|
+
this.setWorker(
|
|
112
|
+
this.workers[msg.data.uuid] ||
|
|
113
|
+
new WebSocketWorker({
|
|
114
|
+
url,
|
|
115
|
+
zustand: this.zustand,
|
|
116
|
+
uuid: msg.data.uuid,
|
|
117
|
+
})
|
|
118
|
+
);
|
|
119
|
+
} else {
|
|
120
|
+
console.error("WorkerManager: unknown worker type", msg);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
//store active worker in window storage
|
|
124
|
+
|
|
125
|
+
return;
|
|
126
|
+
} else if (msg.type === "progress") {
|
|
127
|
+
this.zustand.set_progress(msg as ProgressStateMessage);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
console.error("WorkerManager: unknown message", msg);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
setWorker(worker: FuncNodesWorker | undefined) {
|
|
134
|
+
for (let w in this.workers) {
|
|
135
|
+
if (w !== worker?.uuid) {
|
|
136
|
+
this.workers[w].disconnect();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (worker !== undefined) {
|
|
140
|
+
this.workers[worker.uuid] = worker;
|
|
141
|
+
worker.reconnect();
|
|
142
|
+
}
|
|
143
|
+
window.localStorage.setItem("funcnodes__active_worker", worker?.uuid || "");
|
|
144
|
+
if (this.zustand.worker !== undefined) {
|
|
145
|
+
this.zustand.clear_all();
|
|
146
|
+
}
|
|
147
|
+
this.zustand.worker = worker;
|
|
148
|
+
this.on_setWorker(worker);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async restart_worker(workerid: string) {
|
|
152
|
+
this.ws?.send(JSON.stringify({ type: "restart_worker", workerid }));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private calculateReconnectTimeout(): number {
|
|
156
|
+
// Increase timeout exponentially, capped at maxTimeout
|
|
157
|
+
let timeout = Math.min(
|
|
158
|
+
this.initialTimeout * Math.pow(2, this.reconnectAttempts),
|
|
159
|
+
this.maxTimeout
|
|
160
|
+
);
|
|
161
|
+
return timeout;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private reconnect(): void {
|
|
165
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
166
|
+
let timeout = this.calculateReconnectTimeout();
|
|
167
|
+
console.log(`Attempting to reconnect in ${timeout} ms`);
|
|
168
|
+
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
if (this.ws) {
|
|
171
|
+
if (this.ws.readyState === WebSocket.OPEN) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
this.reconnectAttempts++;
|
|
176
|
+
this.connect();
|
|
177
|
+
}, timeout);
|
|
178
|
+
} else {
|
|
179
|
+
console.warn("Maximum reconnect attempts reached. Giving up.");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
onclose() {
|
|
184
|
+
console.log("WorkerManager: onclose");
|
|
185
|
+
this.reconnect(); // Attempt to reconnect
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
set_active(workerid: string) {
|
|
189
|
+
if (!this.ws) return;
|
|
190
|
+
this.ws.send(JSON.stringify({ type: "set_active", workerid }));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
new_worker({
|
|
194
|
+
name,
|
|
195
|
+
reference,
|
|
196
|
+
copyLib,
|
|
197
|
+
copyNS,
|
|
198
|
+
}: {
|
|
199
|
+
name?: string;
|
|
200
|
+
reference?: string;
|
|
201
|
+
copyLib?: boolean;
|
|
202
|
+
copyNS?: boolean;
|
|
203
|
+
}) {
|
|
204
|
+
if (!name) name = undefined;
|
|
205
|
+
if (!copyLib) copyLib = false;
|
|
206
|
+
if (!copyNS) copyNS = false;
|
|
207
|
+
if (!reference) {
|
|
208
|
+
reference = undefined;
|
|
209
|
+
copyLib = false;
|
|
210
|
+
copyNS = false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (this.ws) {
|
|
214
|
+
this.ws.send(
|
|
215
|
+
JSON.stringify({
|
|
216
|
+
type: "new_worker",
|
|
217
|
+
kwargs: {
|
|
218
|
+
name,
|
|
219
|
+
reference,
|
|
220
|
+
copyLib,
|
|
221
|
+
copyNS,
|
|
222
|
+
},
|
|
223
|
+
})
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export default WorkerManager;
|
package/src/index.css
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
body {
|
|
2
|
+
margin: 0;
|
|
3
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
4
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
5
|
+
sans-serif;
|
|
6
|
+
-webkit-font-smoothing: antialiased;
|
|
7
|
+
-moz-osx-font-smoothing: grayscale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
code {
|
|
11
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
|
12
|
+
monospace;
|
|
13
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom/client';
|
|
3
|
+
import './index.css';
|
|
4
|
+
import App from './App';
|
|
5
|
+
import reportWebVitals from './reportWebVitals';
|
|
6
|
+
|
|
7
|
+
const root = ReactDOM.createRoot(
|
|
8
|
+
document.getElementById('root') as HTMLElement
|
|
9
|
+
);
|
|
10
|
+
root.render(
|
|
11
|
+
<React.StrictMode>
|
|
12
|
+
<App />
|
|
13
|
+
</React.StrictMode>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
// If you want to start measuring performance in your app, pass a function
|
|
17
|
+
// to log results (for example: reportWebVitals(console.log))
|
|
18
|
+
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
|
19
|
+
reportWebVitals();
|
package/src/logo.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="react-scripts" />
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReportHandler } from 'web-vitals';
|
|
2
|
+
|
|
3
|
+
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
|
|
4
|
+
if (onPerfEntry && onPerfEntry instanceof Function) {
|
|
5
|
+
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
|
6
|
+
getCLS(onPerfEntry);
|
|
7
|
+
getFID(onPerfEntry);
|
|
8
|
+
getFCP(onPerfEntry);
|
|
9
|
+
getLCP(onPerfEntry);
|
|
10
|
+
getTTFB(onPerfEntry);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default reportWebVitals;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
interface BaseEdgeAction {
|
|
2
|
+
type: string;
|
|
3
|
+
src_nid: string;
|
|
4
|
+
src_ioid: string;
|
|
5
|
+
trg_nid: string;
|
|
6
|
+
trg_ioid: string;
|
|
7
|
+
from_remote: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface EdgeActionAdd extends BaseEdgeAction {
|
|
11
|
+
type: "add";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface EdgeActionDelete extends BaseEdgeAction {
|
|
15
|
+
type: "delete";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type EdgeAction = EdgeActionAdd | EdgeActionDelete;
|
|
19
|
+
|
|
20
|
+
const generate_edge_id = ({
|
|
21
|
+
src_nid,
|
|
22
|
+
src_ioid,
|
|
23
|
+
trg_nid,
|
|
24
|
+
trg_ioid,
|
|
25
|
+
}: {
|
|
26
|
+
src_nid: string;
|
|
27
|
+
src_ioid: string;
|
|
28
|
+
trg_nid: string;
|
|
29
|
+
trg_ioid: string;
|
|
30
|
+
}) => {
|
|
31
|
+
return [`${src_nid}:${src_ioid}`, `${trg_nid}:${trg_ioid}`].sort().join("--");
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export { generate_edge_id };
|
|
35
|
+
export type { EdgeAction, EdgeActionAdd, EdgeActionDelete };
|