Spaces:
Running
Running
File upload with drag & drop.
Browse files
lynxkite-app/src/lynxkite_app/main.py
CHANGED
@@ -128,6 +128,18 @@ async def service_post(req: fastapi.Request, module_path: str):
|
|
128 |
return await module.api_service_post(req)
|
129 |
|
130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
class SPAStaticFiles(StaticFiles):
|
132 |
"""Route everything to index.html. https://stackoverflow.com/a/73552966/3318517"""
|
133 |
|
|
|
128 |
return await module.api_service_post(req)
|
129 |
|
130 |
|
131 |
+
@app.post("/api/upload")
|
132 |
+
async def upload(req: fastapi.Request):
|
133 |
+
"""Receives file uploads and stores them in DATA_PATH."""
|
134 |
+
form = await req.form()
|
135 |
+
for file in form.values():
|
136 |
+
file_path = config.DATA_PATH / file.filename
|
137 |
+
assert file_path.is_relative_to(config.DATA_PATH), "Invalid file path"
|
138 |
+
with file_path.open("wb") as buffer:
|
139 |
+
shutil.copyfileobj(file.file, buffer)
|
140 |
+
return {"status": "ok"}
|
141 |
+
|
142 |
+
|
143 |
class SPAStaticFiles(StaticFiles):
|
144 |
"""Route everything to index.html. https://stackoverflow.com/a/73552966/3318517"""
|
145 |
|
lynxkite-app/web/package-lock.json
CHANGED
@@ -17,6 +17,7 @@
|
|
17 |
"@syncedstore/react": "^0.6.0",
|
18 |
"@types/node": "^22.10.1",
|
19 |
"@xyflow/react": "^12.3.5",
|
|
|
20 |
"daisyui": "^4.12.20",
|
21 |
"echarts": "^5.5.1",
|
22 |
"fuse.js": "^7.0.0",
|
@@ -2467,6 +2468,12 @@
|
|
2467 |
"license": "MIT",
|
2468 |
"optional": true
|
2469 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
2470 |
"node_modules/autoprefixer": {
|
2471 |
"version": "10.4.20",
|
2472 |
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
|
@@ -2505,6 +2512,17 @@
|
|
2505 |
"postcss": "^8.1.0"
|
2506 |
}
|
2507 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2508 |
"node_modules/bail": {
|
2509 |
"version": "2.0.2",
|
2510 |
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
@@ -2637,6 +2655,19 @@
|
|
2637 |
"ieee754": "^1.1.13"
|
2638 |
}
|
2639 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2640 |
"node_modules/callsites": {
|
2641 |
"version": "3.1.0",
|
2642 |
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
@@ -2824,6 +2855,18 @@
|
|
2824 |
"dev": true,
|
2825 |
"license": "MIT"
|
2826 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2827 |
"node_modules/comma-separated-tokens": {
|
2828 |
"version": "2.0.3",
|
2829 |
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
|
@@ -3126,6 +3169,15 @@
|
|
3126 |
"node": ">=6"
|
3127 |
}
|
3128 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3129 |
"node_modules/dequal": {
|
3130 |
"version": "2.0.3",
|
3131 |
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
@@ -3172,6 +3224,20 @@
|
|
3172 |
"tslib": "^2.0.3"
|
3173 |
}
|
3174 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3175 |
"node_modules/eastasianwidth": {
|
3176 |
"version": "0.2.0",
|
3177 |
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
@@ -3252,6 +3318,51 @@
|
|
3252 |
"is-arrayish": "^0.2.1"
|
3253 |
}
|
3254 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3255 |
"node_modules/esbuild": {
|
3256 |
"version": "0.25.0",
|
3257 |
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
|
@@ -3639,6 +3750,26 @@
|
|
3639 |
"dev": true,
|
3640 |
"license": "ISC"
|
3641 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3642 |
"node_modules/foreground-child": {
|
3643 |
"version": "3.3.0",
|
3644 |
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
@@ -3656,6 +3787,21 @@
|
|
3656 |
"url": "https://github.com/sponsors/isaacs"
|
3657 |
}
|
3658 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3659 |
"node_modules/fraction.js": {
|
3660 |
"version": "4.3.7",
|
3661 |
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
@@ -3689,7 +3835,6 @@
|
|
3689 |
"version": "1.1.2",
|
3690 |
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
3691 |
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
3692 |
-
"dev": true,
|
3693 |
"license": "MIT",
|
3694 |
"funding": {
|
3695 |
"url": "https://github.com/sponsors/ljharb"
|
@@ -3713,6 +3858,43 @@
|
|
3713 |
"node": ">=6.9.0"
|
3714 |
}
|
3715 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3716 |
"node_modules/glob": {
|
3717 |
"version": "10.4.5",
|
3718 |
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
@@ -3785,6 +3967,18 @@
|
|
3785 |
"url": "https://github.com/sponsors/sindresorhus"
|
3786 |
}
|
3787 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3788 |
"node_modules/graphemer": {
|
3789 |
"version": "1.4.0",
|
3790 |
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
@@ -3802,11 +3996,37 @@
|
|
3802 |
"node": ">=8"
|
3803 |
}
|
3804 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3805 |
"node_modules/hasown": {
|
3806 |
"version": "2.0.2",
|
3807 |
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
3808 |
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
3809 |
-
"dev": true,
|
3810 |
"license": "MIT",
|
3811 |
"dependencies": {
|
3812 |
"function-bind": "^1.1.2"
|
@@ -4523,6 +4743,15 @@
|
|
4523 |
"license": "MIT",
|
4524 |
"optional": true
|
4525 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4526 |
"node_modules/mdast-util-from-markdown": {
|
4527 |
"version": "2.0.2",
|
4528 |
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
@@ -5142,6 +5371,27 @@
|
|
5142 |
"node": ">=8.6"
|
5143 |
}
|
5144 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5145 |
"node_modules/minimatch": {
|
5146 |
"version": "3.1.2",
|
5147 |
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
@@ -5766,6 +6016,12 @@
|
|
5766 |
"url": "https://github.com/sponsors/wooorm"
|
5767 |
}
|
5768 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
5769 |
"node_modules/prr": {
|
5770 |
"version": "1.0.1",
|
5771 |
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
|
|
17 |
"@syncedstore/react": "^0.6.0",
|
18 |
"@types/node": "^22.10.1",
|
19 |
"@xyflow/react": "^12.3.5",
|
20 |
+
"axios": "^1.8.2",
|
21 |
"daisyui": "^4.12.20",
|
22 |
"echarts": "^5.5.1",
|
23 |
"fuse.js": "^7.0.0",
|
|
|
2468 |
"license": "MIT",
|
2469 |
"optional": true
|
2470 |
},
|
2471 |
+
"node_modules/asynckit": {
|
2472 |
+
"version": "0.4.0",
|
2473 |
+
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
2474 |
+
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
2475 |
+
"license": "MIT"
|
2476 |
+
},
|
2477 |
"node_modules/autoprefixer": {
|
2478 |
"version": "10.4.20",
|
2479 |
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
|
|
|
2512 |
"postcss": "^8.1.0"
|
2513 |
}
|
2514 |
},
|
2515 |
+
"node_modules/axios": {
|
2516 |
+
"version": "1.8.2",
|
2517 |
+
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz",
|
2518 |
+
"integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==",
|
2519 |
+
"license": "MIT",
|
2520 |
+
"dependencies": {
|
2521 |
+
"follow-redirects": "^1.15.6",
|
2522 |
+
"form-data": "^4.0.0",
|
2523 |
+
"proxy-from-env": "^1.1.0"
|
2524 |
+
}
|
2525 |
+
},
|
2526 |
"node_modules/bail": {
|
2527 |
"version": "2.0.2",
|
2528 |
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
|
|
2655 |
"ieee754": "^1.1.13"
|
2656 |
}
|
2657 |
},
|
2658 |
+
"node_modules/call-bind-apply-helpers": {
|
2659 |
+
"version": "1.0.2",
|
2660 |
+
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
2661 |
+
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
2662 |
+
"license": "MIT",
|
2663 |
+
"dependencies": {
|
2664 |
+
"es-errors": "^1.3.0",
|
2665 |
+
"function-bind": "^1.1.2"
|
2666 |
+
},
|
2667 |
+
"engines": {
|
2668 |
+
"node": ">= 0.4"
|
2669 |
+
}
|
2670 |
+
},
|
2671 |
"node_modules/callsites": {
|
2672 |
"version": "3.1.0",
|
2673 |
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
|
|
2855 |
"dev": true,
|
2856 |
"license": "MIT"
|
2857 |
},
|
2858 |
+
"node_modules/combined-stream": {
|
2859 |
+
"version": "1.0.8",
|
2860 |
+
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
2861 |
+
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
2862 |
+
"license": "MIT",
|
2863 |
+
"dependencies": {
|
2864 |
+
"delayed-stream": "~1.0.0"
|
2865 |
+
},
|
2866 |
+
"engines": {
|
2867 |
+
"node": ">= 0.8"
|
2868 |
+
}
|
2869 |
+
},
|
2870 |
"node_modules/comma-separated-tokens": {
|
2871 |
"version": "2.0.3",
|
2872 |
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
|
|
|
3169 |
"node": ">=6"
|
3170 |
}
|
3171 |
},
|
3172 |
+
"node_modules/delayed-stream": {
|
3173 |
+
"version": "1.0.0",
|
3174 |
+
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
3175 |
+
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
3176 |
+
"license": "MIT",
|
3177 |
+
"engines": {
|
3178 |
+
"node": ">=0.4.0"
|
3179 |
+
}
|
3180 |
+
},
|
3181 |
"node_modules/dequal": {
|
3182 |
"version": "2.0.3",
|
3183 |
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
|
|
3224 |
"tslib": "^2.0.3"
|
3225 |
}
|
3226 |
},
|
3227 |
+
"node_modules/dunder-proto": {
|
3228 |
+
"version": "1.0.1",
|
3229 |
+
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
3230 |
+
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
3231 |
+
"license": "MIT",
|
3232 |
+
"dependencies": {
|
3233 |
+
"call-bind-apply-helpers": "^1.0.1",
|
3234 |
+
"es-errors": "^1.3.0",
|
3235 |
+
"gopd": "^1.2.0"
|
3236 |
+
},
|
3237 |
+
"engines": {
|
3238 |
+
"node": ">= 0.4"
|
3239 |
+
}
|
3240 |
+
},
|
3241 |
"node_modules/eastasianwidth": {
|
3242 |
"version": "0.2.0",
|
3243 |
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
|
|
3318 |
"is-arrayish": "^0.2.1"
|
3319 |
}
|
3320 |
},
|
3321 |
+
"node_modules/es-define-property": {
|
3322 |
+
"version": "1.0.1",
|
3323 |
+
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
3324 |
+
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
3325 |
+
"license": "MIT",
|
3326 |
+
"engines": {
|
3327 |
+
"node": ">= 0.4"
|
3328 |
+
}
|
3329 |
+
},
|
3330 |
+
"node_modules/es-errors": {
|
3331 |
+
"version": "1.3.0",
|
3332 |
+
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
3333 |
+
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
3334 |
+
"license": "MIT",
|
3335 |
+
"engines": {
|
3336 |
+
"node": ">= 0.4"
|
3337 |
+
}
|
3338 |
+
},
|
3339 |
+
"node_modules/es-object-atoms": {
|
3340 |
+
"version": "1.1.1",
|
3341 |
+
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
3342 |
+
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
3343 |
+
"license": "MIT",
|
3344 |
+
"dependencies": {
|
3345 |
+
"es-errors": "^1.3.0"
|
3346 |
+
},
|
3347 |
+
"engines": {
|
3348 |
+
"node": ">= 0.4"
|
3349 |
+
}
|
3350 |
+
},
|
3351 |
+
"node_modules/es-set-tostringtag": {
|
3352 |
+
"version": "2.1.0",
|
3353 |
+
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
3354 |
+
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
3355 |
+
"license": "MIT",
|
3356 |
+
"dependencies": {
|
3357 |
+
"es-errors": "^1.3.0",
|
3358 |
+
"get-intrinsic": "^1.2.6",
|
3359 |
+
"has-tostringtag": "^1.0.2",
|
3360 |
+
"hasown": "^2.0.2"
|
3361 |
+
},
|
3362 |
+
"engines": {
|
3363 |
+
"node": ">= 0.4"
|
3364 |
+
}
|
3365 |
+
},
|
3366 |
"node_modules/esbuild": {
|
3367 |
"version": "0.25.0",
|
3368 |
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
|
|
|
3750 |
"dev": true,
|
3751 |
"license": "ISC"
|
3752 |
},
|
3753 |
+
"node_modules/follow-redirects": {
|
3754 |
+
"version": "1.15.9",
|
3755 |
+
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
3756 |
+
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
3757 |
+
"funding": [
|
3758 |
+
{
|
3759 |
+
"type": "individual",
|
3760 |
+
"url": "https://github.com/sponsors/RubenVerborgh"
|
3761 |
+
}
|
3762 |
+
],
|
3763 |
+
"license": "MIT",
|
3764 |
+
"engines": {
|
3765 |
+
"node": ">=4.0"
|
3766 |
+
},
|
3767 |
+
"peerDependenciesMeta": {
|
3768 |
+
"debug": {
|
3769 |
+
"optional": true
|
3770 |
+
}
|
3771 |
+
}
|
3772 |
+
},
|
3773 |
"node_modules/foreground-child": {
|
3774 |
"version": "3.3.0",
|
3775 |
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
|
|
3787 |
"url": "https://github.com/sponsors/isaacs"
|
3788 |
}
|
3789 |
},
|
3790 |
+
"node_modules/form-data": {
|
3791 |
+
"version": "4.0.2",
|
3792 |
+
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
3793 |
+
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
3794 |
+
"license": "MIT",
|
3795 |
+
"dependencies": {
|
3796 |
+
"asynckit": "^0.4.0",
|
3797 |
+
"combined-stream": "^1.0.8",
|
3798 |
+
"es-set-tostringtag": "^2.1.0",
|
3799 |
+
"mime-types": "^2.1.12"
|
3800 |
+
},
|
3801 |
+
"engines": {
|
3802 |
+
"node": ">= 6"
|
3803 |
+
}
|
3804 |
+
},
|
3805 |
"node_modules/fraction.js": {
|
3806 |
"version": "4.3.7",
|
3807 |
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
|
|
3835 |
"version": "1.1.2",
|
3836 |
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
3837 |
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
|
|
3838 |
"license": "MIT",
|
3839 |
"funding": {
|
3840 |
"url": "https://github.com/sponsors/ljharb"
|
|
|
3858 |
"node": ">=6.9.0"
|
3859 |
}
|
3860 |
},
|
3861 |
+
"node_modules/get-intrinsic": {
|
3862 |
+
"version": "1.3.0",
|
3863 |
+
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
3864 |
+
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
3865 |
+
"license": "MIT",
|
3866 |
+
"dependencies": {
|
3867 |
+
"call-bind-apply-helpers": "^1.0.2",
|
3868 |
+
"es-define-property": "^1.0.1",
|
3869 |
+
"es-errors": "^1.3.0",
|
3870 |
+
"es-object-atoms": "^1.1.1",
|
3871 |
+
"function-bind": "^1.1.2",
|
3872 |
+
"get-proto": "^1.0.1",
|
3873 |
+
"gopd": "^1.2.0",
|
3874 |
+
"has-symbols": "^1.1.0",
|
3875 |
+
"hasown": "^2.0.2",
|
3876 |
+
"math-intrinsics": "^1.1.0"
|
3877 |
+
},
|
3878 |
+
"engines": {
|
3879 |
+
"node": ">= 0.4"
|
3880 |
+
},
|
3881 |
+
"funding": {
|
3882 |
+
"url": "https://github.com/sponsors/ljharb"
|
3883 |
+
}
|
3884 |
+
},
|
3885 |
+
"node_modules/get-proto": {
|
3886 |
+
"version": "1.0.1",
|
3887 |
+
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
3888 |
+
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
3889 |
+
"license": "MIT",
|
3890 |
+
"dependencies": {
|
3891 |
+
"dunder-proto": "^1.0.1",
|
3892 |
+
"es-object-atoms": "^1.0.0"
|
3893 |
+
},
|
3894 |
+
"engines": {
|
3895 |
+
"node": ">= 0.4"
|
3896 |
+
}
|
3897 |
+
},
|
3898 |
"node_modules/glob": {
|
3899 |
"version": "10.4.5",
|
3900 |
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
|
|
3967 |
"url": "https://github.com/sponsors/sindresorhus"
|
3968 |
}
|
3969 |
},
|
3970 |
+
"node_modules/gopd": {
|
3971 |
+
"version": "1.2.0",
|
3972 |
+
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
3973 |
+
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
3974 |
+
"license": "MIT",
|
3975 |
+
"engines": {
|
3976 |
+
"node": ">= 0.4"
|
3977 |
+
},
|
3978 |
+
"funding": {
|
3979 |
+
"url": "https://github.com/sponsors/ljharb"
|
3980 |
+
}
|
3981 |
+
},
|
3982 |
"node_modules/graphemer": {
|
3983 |
"version": "1.4.0",
|
3984 |
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
|
|
3996 |
"node": ">=8"
|
3997 |
}
|
3998 |
},
|
3999 |
+
"node_modules/has-symbols": {
|
4000 |
+
"version": "1.1.0",
|
4001 |
+
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
4002 |
+
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
4003 |
+
"license": "MIT",
|
4004 |
+
"engines": {
|
4005 |
+
"node": ">= 0.4"
|
4006 |
+
},
|
4007 |
+
"funding": {
|
4008 |
+
"url": "https://github.com/sponsors/ljharb"
|
4009 |
+
}
|
4010 |
+
},
|
4011 |
+
"node_modules/has-tostringtag": {
|
4012 |
+
"version": "1.0.2",
|
4013 |
+
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
4014 |
+
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
4015 |
+
"license": "MIT",
|
4016 |
+
"dependencies": {
|
4017 |
+
"has-symbols": "^1.0.3"
|
4018 |
+
},
|
4019 |
+
"engines": {
|
4020 |
+
"node": ">= 0.4"
|
4021 |
+
},
|
4022 |
+
"funding": {
|
4023 |
+
"url": "https://github.com/sponsors/ljharb"
|
4024 |
+
}
|
4025 |
+
},
|
4026 |
"node_modules/hasown": {
|
4027 |
"version": "2.0.2",
|
4028 |
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
4029 |
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
|
|
4030 |
"license": "MIT",
|
4031 |
"dependencies": {
|
4032 |
"function-bind": "^1.1.2"
|
|
|
4743 |
"license": "MIT",
|
4744 |
"optional": true
|
4745 |
},
|
4746 |
+
"node_modules/math-intrinsics": {
|
4747 |
+
"version": "1.1.0",
|
4748 |
+
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
4749 |
+
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
4750 |
+
"license": "MIT",
|
4751 |
+
"engines": {
|
4752 |
+
"node": ">= 0.4"
|
4753 |
+
}
|
4754 |
+
},
|
4755 |
"node_modules/mdast-util-from-markdown": {
|
4756 |
"version": "2.0.2",
|
4757 |
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
|
|
5371 |
"node": ">=8.6"
|
5372 |
}
|
5373 |
},
|
5374 |
+
"node_modules/mime-db": {
|
5375 |
+
"version": "1.52.0",
|
5376 |
+
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
5377 |
+
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
5378 |
+
"license": "MIT",
|
5379 |
+
"engines": {
|
5380 |
+
"node": ">= 0.6"
|
5381 |
+
}
|
5382 |
+
},
|
5383 |
+
"node_modules/mime-types": {
|
5384 |
+
"version": "2.1.35",
|
5385 |
+
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
5386 |
+
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
5387 |
+
"license": "MIT",
|
5388 |
+
"dependencies": {
|
5389 |
+
"mime-db": "1.52.0"
|
5390 |
+
},
|
5391 |
+
"engines": {
|
5392 |
+
"node": ">= 0.6"
|
5393 |
+
}
|
5394 |
+
},
|
5395 |
"node_modules/minimatch": {
|
5396 |
"version": "3.1.2",
|
5397 |
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
|
|
6016 |
"url": "https://github.com/sponsors/wooorm"
|
6017 |
}
|
6018 |
},
|
6019 |
+
"node_modules/proxy-from-env": {
|
6020 |
+
"version": "1.1.0",
|
6021 |
+
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
6022 |
+
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
6023 |
+
"license": "MIT"
|
6024 |
+
},
|
6025 |
"node_modules/prr": {
|
6026 |
"version": "1.0.1",
|
6027 |
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
lynxkite-app/web/package.json
CHANGED
@@ -20,6 +20,7 @@
|
|
20 |
"@syncedstore/react": "^0.6.0",
|
21 |
"@types/node": "^22.10.1",
|
22 |
"@xyflow/react": "^12.3.5",
|
|
|
23 |
"daisyui": "^4.12.20",
|
24 |
"echarts": "^5.5.1",
|
25 |
"fuse.js": "^7.0.0",
|
@@ -35,6 +36,8 @@
|
|
35 |
},
|
36 |
"devDependencies": {
|
37 |
"@eslint/js": "^9.15.0",
|
|
|
|
|
38 |
"@types/react": "^18.3.14",
|
39 |
"@types/react-dom": "^18.3.2",
|
40 |
"@vitejs/plugin-react-swc": "^3.5.0",
|
@@ -47,9 +50,7 @@
|
|
47 |
"tailwindcss": "^3.4.16",
|
48 |
"typescript": "~5.6.2",
|
49 |
"typescript-eslint": "^8.15.0",
|
50 |
-
"vite": "^6.2.0"
|
51 |
-
"@playwright/test": "^1.50.1",
|
52 |
-
"@types/node": "^22.13.1"
|
53 |
},
|
54 |
"optionalDependencies": {
|
55 |
"@rollup/rollup-linux-x64-gnu": "^4.28.1"
|
|
|
20 |
"@syncedstore/react": "^0.6.0",
|
21 |
"@types/node": "^22.10.1",
|
22 |
"@xyflow/react": "^12.3.5",
|
23 |
+
"axios": "^1.8.2",
|
24 |
"daisyui": "^4.12.20",
|
25 |
"echarts": "^5.5.1",
|
26 |
"fuse.js": "^7.0.0",
|
|
|
36 |
},
|
37 |
"devDependencies": {
|
38 |
"@eslint/js": "^9.15.0",
|
39 |
+
"@playwright/test": "^1.50.1",
|
40 |
+
"@types/node": "^22.13.1",
|
41 |
"@types/react": "^18.3.14",
|
42 |
"@types/react-dom": "^18.3.2",
|
43 |
"@vitejs/plugin-react-swc": "^3.5.0",
|
|
|
50 |
"tailwindcss": "^3.4.16",
|
51 |
"typescript": "~5.6.2",
|
52 |
"typescript-eslint": "^8.15.0",
|
53 |
+
"vite": "^6.2.0"
|
|
|
|
|
54 |
},
|
55 |
"optionalDependencies": {
|
56 |
"@rollup/rollup-linux-x64-gnu": "^4.28.1"
|
lynxkite-app/web/src/index.css
CHANGED
@@ -240,6 +240,22 @@ body {
|
|
240 |
background: transparent;
|
241 |
color: #39bcf3;
|
242 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
}
|
244 |
|
245 |
.params-expander {
|
|
|
240 |
background: transparent;
|
241 |
color: #39bcf3;
|
242 |
}
|
243 |
+
|
244 |
+
.workspace-message {
|
245 |
+
position: absolute;
|
246 |
+
left: 50%;
|
247 |
+
bottom: 20px;
|
248 |
+
transform: translateX(-50%);
|
249 |
+
box-shadow: 0 5px 50px 0px #8008;
|
250 |
+
padding: 10px 40px 10px 20px;
|
251 |
+
border-radius: 5px;
|
252 |
+
|
253 |
+
.close {
|
254 |
+
position: absolute;
|
255 |
+
right: 10px;
|
256 |
+
cursor: pointer;
|
257 |
+
}
|
258 |
+
}
|
259 |
}
|
260 |
|
261 |
.params-expander {
|
lynxkite-app/web/src/workspace/Workspace.tsx
CHANGED
@@ -14,6 +14,7 @@ import {
|
|
14 |
useReactFlow,
|
15 |
useUpdateNodeInternals,
|
16 |
} from "@xyflow/react";
|
|
|
17 |
import {
|
18 |
type MouseEvent,
|
19 |
useCallback,
|
@@ -62,6 +63,7 @@ function LynxKiteFlow() {
|
|
62 |
const [edges, setEdges] = useState([] as Edge[]);
|
63 |
const { path } = useParams();
|
64 |
const [state, setState] = useState({ workspace: {} as Workspace });
|
|
|
65 |
useEffect(() => {
|
66 |
const state = syncedStore({ workspace: {} as Workspace });
|
67 |
setState(state);
|
@@ -236,33 +238,44 @@ function LynxKiteFlow() {
|
|
236 |
},
|
237 |
[catalog, state, nodeSearchSettings, suppressSearchUntil, closeNodeSearch],
|
238 |
);
|
239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
(meta: OpsOp) => {
|
241 |
-
const node
|
242 |
-
type: meta.type,
|
243 |
-
data: {
|
244 |
-
meta: meta,
|
245 |
-
title: meta.name,
|
246 |
-
params: Object.fromEntries(
|
247 |
-
Object.values(meta.params).map((p) => [p.name, p.default]),
|
248 |
-
),
|
249 |
-
},
|
250 |
-
};
|
251 |
const nss = nodeSearchSettings!;
|
252 |
node.position = reactFlow.screenToFlowPosition({
|
253 |
x: nss.pos.x,
|
254 |
y: nss.pos.y,
|
255 |
});
|
256 |
-
|
257 |
-
let i = 1;
|
258 |
-
node.id = `${title} ${i}`;
|
259 |
-
const wnodes = state.workspace.nodes!;
|
260 |
-
while (wnodes.find((x) => x.id === node.id)) {
|
261 |
-
i += 1;
|
262 |
-
node.id = `${title} ${i}`;
|
263 |
-
}
|
264 |
-
wnodes.push(node as WorkspaceNode);
|
265 |
-
setNodes([...nodes, node as WorkspaceNode]);
|
266 |
closeNodeSearch();
|
267 |
},
|
268 |
[nodeSearchSettings, state, reactFlow, nodes, closeNodeSearch],
|
@@ -284,6 +297,39 @@ function LynxKiteFlow() {
|
|
284 |
[state],
|
285 |
);
|
286 |
const parentDir = path!.split("/").slice(0, -1).join("/");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
return (
|
288 |
<div className="workspace">
|
289 |
<div className="top-bar bg-neutral">
|
@@ -310,7 +356,11 @@ function LynxKiteFlow() {
|
|
310 |
</a>
|
311 |
</div>
|
312 |
</div>
|
313 |
-
<div
|
|
|
|
|
|
|
|
|
314 |
<LynxKiteState.Provider value={state}>
|
315 |
<ReactFlow
|
316 |
nodes={nodes}
|
@@ -344,11 +394,19 @@ function LynxKiteFlow() {
|
|
344 |
pos={nodeSearchSettings.pos}
|
345 |
boxes={nodeSearchSettings.boxes}
|
346 |
onCancel={closeNodeSearch}
|
347 |
-
onAdd={
|
348 |
/>
|
349 |
)}
|
350 |
</ReactFlow>
|
351 |
</LynxKiteState.Provider>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
352 |
</div>
|
353 |
</div>
|
354 |
);
|
|
|
14 |
useReactFlow,
|
15 |
useUpdateNodeInternals,
|
16 |
} from "@xyflow/react";
|
17 |
+
import axios from "axios";
|
18 |
import {
|
19 |
type MouseEvent,
|
20 |
useCallback,
|
|
|
63 |
const [edges, setEdges] = useState([] as Edge[]);
|
64 |
const { path } = useParams();
|
65 |
const [state, setState] = useState({ workspace: {} as Workspace });
|
66 |
+
const [message, setMessage] = useState(null as string | null);
|
67 |
useEffect(() => {
|
68 |
const state = syncedStore({ workspace: {} as Workspace });
|
69 |
setState(state);
|
|
|
238 |
},
|
239 |
[catalog, state, nodeSearchSettings, suppressSearchUntil, closeNodeSearch],
|
240 |
);
|
241 |
+
function addNode(
|
242 |
+
node: Partial<WorkspaceNode>,
|
243 |
+
state: { workspace: Workspace },
|
244 |
+
nodes: Node[],
|
245 |
+
) {
|
246 |
+
const title = node.title;
|
247 |
+
let i = 1;
|
248 |
+
node.id = `${title} ${i}`;
|
249 |
+
const wnodes = state.workspace.nodes!;
|
250 |
+
while (wnodes.find((x) => x.id === node.id)) {
|
251 |
+
i += 1;
|
252 |
+
node.id = `${title} ${i}`;
|
253 |
+
}
|
254 |
+
wnodes.push(node as WorkspaceNode);
|
255 |
+
setNodes([...nodes, node as WorkspaceNode]);
|
256 |
+
}
|
257 |
+
function nodeFromMeta(meta: OpsOp): Partial<WorkspaceNode> {
|
258 |
+
const node: Partial<WorkspaceNode> = {
|
259 |
+
type: meta.type,
|
260 |
+
data: {
|
261 |
+
meta: meta,
|
262 |
+
title: meta.name,
|
263 |
+
params: Object.fromEntries(
|
264 |
+
Object.values(meta.params).map((p) => [p.name, p.default]),
|
265 |
+
),
|
266 |
+
},
|
267 |
+
};
|
268 |
+
return node;
|
269 |
+
}
|
270 |
+
const addNodeFromSearch = useCallback(
|
271 |
(meta: OpsOp) => {
|
272 |
+
const node = nodeFromMeta(meta);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
const nss = nodeSearchSettings!;
|
274 |
node.position = reactFlow.screenToFlowPosition({
|
275 |
x: nss.pos.x,
|
276 |
y: nss.pos.y,
|
277 |
});
|
278 |
+
addNode(node, state, nodes);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
closeNodeSearch();
|
280 |
},
|
281 |
[nodeSearchSettings, state, reactFlow, nodes, closeNodeSearch],
|
|
|
297 |
[state],
|
298 |
);
|
299 |
const parentDir = path!.split("/").slice(0, -1).join("/");
|
300 |
+
function onDragOver(e: React.DragEvent<HTMLDivElement>) {
|
301 |
+
e.stopPropagation();
|
302 |
+
e.preventDefault();
|
303 |
+
}
|
304 |
+
async function onDrop(e: React.DragEvent<HTMLDivElement>) {
|
305 |
+
e.stopPropagation();
|
306 |
+
e.preventDefault();
|
307 |
+
const file = e.dataTransfer.files[0];
|
308 |
+
const formData = new FormData();
|
309 |
+
formData.append("file", file);
|
310 |
+
try {
|
311 |
+
await axios.post("/api/upload", formData, {
|
312 |
+
onUploadProgress: (progressEvent) => {
|
313 |
+
const percentCompleted = Math.round(
|
314 |
+
(100 * progressEvent.loaded) / progressEvent.total!,
|
315 |
+
);
|
316 |
+
if (percentCompleted === 100) setMessage("Processing file...");
|
317 |
+
else setMessage(`Uploading ${percentCompleted}%`);
|
318 |
+
},
|
319 |
+
});
|
320 |
+
setMessage(null);
|
321 |
+
const cat = catalog.data![state.workspace.env!];
|
322 |
+
const node = nodeFromMeta(cat["Import file"]);
|
323 |
+
node.position = reactFlow.screenToFlowPosition({
|
324 |
+
x: e.clientX,
|
325 |
+
y: e.clientY,
|
326 |
+
});
|
327 |
+
node.data!.params.file_path = file.name;
|
328 |
+
addNode(node, state, nodes);
|
329 |
+
} catch (error) {
|
330 |
+
setMessage("File upload failed.");
|
331 |
+
}
|
332 |
+
}
|
333 |
return (
|
334 |
<div className="workspace">
|
335 |
<div className="top-bar bg-neutral">
|
|
|
356 |
</a>
|
357 |
</div>
|
358 |
</div>
|
359 |
+
<div
|
360 |
+
style={{ height: "100%", width: "100vw" }}
|
361 |
+
onDragOver={onDragOver}
|
362 |
+
onDrop={onDrop}
|
363 |
+
>
|
364 |
<LynxKiteState.Provider value={state}>
|
365 |
<ReactFlow
|
366 |
nodes={nodes}
|
|
|
394 |
pos={nodeSearchSettings.pos}
|
395 |
boxes={nodeSearchSettings.boxes}
|
396 |
onCancel={closeNodeSearch}
|
397 |
+
onAdd={addNodeFromSearch}
|
398 |
/>
|
399 |
)}
|
400 |
</ReactFlow>
|
401 |
</LynxKiteState.Provider>
|
402 |
+
{message && (
|
403 |
+
<div className="workspace-message">
|
404 |
+
<span className="close" onClick={() => setMessage(null)}>
|
405 |
+
<Close />
|
406 |
+
</span>
|
407 |
+
{message}
|
408 |
+
</div>
|
409 |
+
)}
|
410 |
</div>
|
411 |
</div>
|
412 |
);
|