Spaces:
Running
Running
Put metadata in the nodes.
Browse files- server/main.py +1 -1
- server/workspace.py +30 -0
- web/src/LynxKiteFlow.svelte +2 -5
- web/src/NodeParameter.svelte +1 -1
- web/src/NodeSearch.svelte +1 -1
- web/src/NodeWithArea.svelte +1 -3
- web/src/NodeWithParams.svelte +1 -3
- web/src/NodeWithParamsVertical.svelte +1 -3
server/main.py
CHANGED
@@ -13,7 +13,7 @@ app = fastapi.FastAPI()
|
|
13 |
|
14 |
@app.get("/api/catalog")
|
15 |
def get_catalog():
|
16 |
-
return
|
17 |
|
18 |
|
19 |
class SaveRequest(workspace.BaseConfig):
|
|
|
13 |
|
14 |
@app.get("/api/catalog")
|
15 |
def get_catalog():
|
16 |
+
return {op.name: op.model_dump() for op in ops.ALL_OPS.values()}
|
17 |
|
18 |
|
19 |
class SaveRequest(workspace.BaseConfig):
|
server/workspace.py
CHANGED
@@ -93,4 +93,34 @@ def load(path: str):
|
|
93 |
with open(path) as f:
|
94 |
j = f.read()
|
95 |
ws = Workspace.model_validate_json(j)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
return ws
|
|
|
93 |
with open(path) as f:
|
94 |
j = f.read()
|
95 |
ws = Workspace.model_validate_json(j)
|
96 |
+
# Metadata is added after loading. This way code changes take effect on old boxes too.
|
97 |
+
_update_metadata(ws)
|
98 |
+
return ws
|
99 |
+
|
100 |
+
|
101 |
+
def _update_metadata(ws):
|
102 |
+
nodes = {node.id: node for node in ws.nodes}
|
103 |
+
done = set()
|
104 |
+
while len(done) < len(nodes):
|
105 |
+
for node in ws.nodes:
|
106 |
+
if node.id in done:
|
107 |
+
continue
|
108 |
+
data = node.data
|
109 |
+
if node.parentId is None:
|
110 |
+
op = ops.ALL_OPS.get(data.title)
|
111 |
+
elif node.parentId not in nodes:
|
112 |
+
data.error = f'Parent not found: {node.parentId}'
|
113 |
+
done.add(node.id)
|
114 |
+
continue
|
115 |
+
elif node.parentId in done:
|
116 |
+
op = nodes[node.parentId].data.meta.sub_nodes[data.title]
|
117 |
+
else:
|
118 |
+
continue
|
119 |
+
if op:
|
120 |
+
data.meta = op
|
121 |
+
if data.error == 'Unknown operation.':
|
122 |
+
data.error = None
|
123 |
+
else:
|
124 |
+
data.error = 'Unknown operation.'
|
125 |
+
done.add(node.id)
|
126 |
return ws
|
web/src/LynxKiteFlow.svelte
CHANGED
@@ -84,6 +84,7 @@
|
|
84 |
const node = {
|
85 |
type: meta.type,
|
86 |
data: {
|
|
|
87 |
title: meta.name,
|
88 |
params: Object.fromEntries(
|
89 |
Object.values(meta.params).map((p) => [p.name, p.default])),
|
@@ -153,13 +154,9 @@
|
|
153 |
|| e.targetHandle !== connection.targetHandle);
|
154 |
});
|
155 |
}
|
156 |
-
function getMeta(title) {
|
157 |
-
return $boxes.find((m) => m.data.title === title);
|
158 |
-
}
|
159 |
-
setContext('LynxKiteFlow', { getMeta });
|
160 |
function nodeClick(e) {
|
161 |
const node = e.detail.node;
|
162 |
-
const meta =
|
163 |
if (!meta) return;
|
164 |
const sub_nodes = meta.sub_nodes;
|
165 |
if (!sub_nodes) return;
|
|
|
84 |
const node = {
|
85 |
type: meta.type,
|
86 |
data: {
|
87 |
+
meta: meta,
|
88 |
title: meta.name,
|
89 |
params: Object.fromEntries(
|
90 |
Object.values(meta.params).map((p) => [p.name, p.default])),
|
|
|
154 |
|| e.targetHandle !== connection.targetHandle);
|
155 |
});
|
156 |
}
|
|
|
|
|
|
|
|
|
157 |
function nodeClick(e) {
|
158 |
const node = e.detail.node;
|
159 |
+
const meta = node.data.meta;
|
160 |
if (!meta) return;
|
161 |
const sub_nodes = meta.sub_nodes;
|
162 |
if (!sub_nodes) return;
|
web/src/NodeParameter.svelte
CHANGED
@@ -13,7 +13,7 @@
|
|
13 |
</button>
|
14 |
{:else if meta?.type?.enum}
|
15 |
<select class="form-select form-select-sm"
|
16 |
-
value={value}
|
17 |
on:change={(evt) => onChange(evt.currentTarget.value)}
|
18 |
>
|
19 |
{#each meta.type.enum as option}
|
|
|
13 |
</button>
|
14 |
{:else if meta?.type?.enum}
|
15 |
<select class="form-select form-select-sm"
|
16 |
+
value={value || meta.type.enum[0]}
|
17 |
on:change={(evt) => onChange(evt.currentTarget.value)}
|
18 |
>
|
19 |
{#each meta.type.enum as option}
|
web/src/NodeSearch.svelte
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
export let pos;
|
6 |
export let boxes;
|
7 |
let searchBox: HTMLInputElement;
|
8 |
-
let hits = boxes.map(box => ({item: box}));
|
9 |
let selectedIndex = 0;
|
10 |
onMount(() => searchBox.focus());
|
11 |
$: fuse = new Fuse(boxes, {
|
|
|
5 |
export let pos;
|
6 |
export let boxes;
|
7 |
let searchBox: HTMLInputElement;
|
8 |
+
let hits = Object.values(boxes).map(box => ({item: box}));
|
9 |
let selectedIndex = 0;
|
10 |
onMount(() => searchBox.focus());
|
11 |
$: fuse = new Fuse(boxes, {
|
web/src/NodeWithArea.svelte
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { getContext } from 'svelte';
|
3 |
import { type NodeProps, useSvelteFlow } from '@xyflow/svelte';
|
4 |
import NodeParameter from './NodeParameter.svelte';
|
5 |
|
@@ -25,8 +24,7 @@
|
|
25 |
return n ? n + 'px' : undefined;
|
26 |
}
|
27 |
const { updateNodeData } = useSvelteFlow();
|
28 |
-
$:
|
29 |
-
$: metaParams = meta && Object.fromEntries(meta.data.params.map((p) => [p.name, p]));
|
30 |
</script>
|
31 |
|
32 |
<div class="area" style:width={asPx(width)} style:height={asPx(height)} style={containerStyle}>
|
|
|
1 |
<script lang="ts">
|
|
|
2 |
import { type NodeProps, useSvelteFlow } from '@xyflow/svelte';
|
3 |
import NodeParameter from './NodeParameter.svelte';
|
4 |
|
|
|
24 |
return n ? n + 'px' : undefined;
|
25 |
}
|
26 |
const { updateNodeData } = useSvelteFlow();
|
27 |
+
$: metaParams = data.meta?.params;
|
|
|
28 |
</script>
|
29 |
|
30 |
<div class="area" style:width={asPx(width)} style:height={asPx(height)} style={containerStyle}>
|
web/src/NodeWithParams.svelte
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { getContext } from 'svelte';
|
3 |
import { type NodeProps, useSvelteFlow } from '@xyflow/svelte';
|
4 |
import LynxKiteNode from './LynxKiteNode.svelte';
|
5 |
import NodeParameter from './NodeParameter.svelte';
|
@@ -7,8 +6,7 @@
|
|
7 |
export let id: $$Props['id'];
|
8 |
export let data: $$Props['data'];
|
9 |
const { updateNodeData } = useSvelteFlow();
|
10 |
-
$:
|
11 |
-
$: metaParams = meta && Object.fromEntries(meta.data.params.map((p) => [p.name, p]));
|
12 |
</script>
|
13 |
|
14 |
<LynxKiteNode {...$$props}>
|
|
|
1 |
<script lang="ts">
|
|
|
2 |
import { type NodeProps, useSvelteFlow } from '@xyflow/svelte';
|
3 |
import LynxKiteNode from './LynxKiteNode.svelte';
|
4 |
import NodeParameter from './NodeParameter.svelte';
|
|
|
6 |
export let id: $$Props['id'];
|
7 |
export let data: $$Props['data'];
|
8 |
const { updateNodeData } = useSvelteFlow();
|
9 |
+
$: metaParams = data.meta?.params;
|
|
|
10 |
</script>
|
11 |
|
12 |
<LynxKiteNode {...$$props}>
|
web/src/NodeWithParamsVertical.svelte
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { getContext } from 'svelte';
|
3 |
import { type NodeProps, useSvelteFlow } from '@xyflow/svelte';
|
4 |
import LynxKiteNode from './LynxKiteNode.svelte';
|
5 |
import NodeParameter from './NodeParameter.svelte';
|
@@ -7,8 +6,7 @@
|
|
7 |
export let id: $$Props['id'];
|
8 |
export let data: $$Props['data'];
|
9 |
const { updateNodeData } = useSvelteFlow();
|
10 |
-
$:
|
11 |
-
$: metaParams = meta && Object.fromEntries(meta.data.params.map((p) => [p.name, p]));
|
12 |
</script>
|
13 |
|
14 |
<LynxKiteNode {...$$props} sourcePosition="top" targetPosition="bottom">
|
|
|
1 |
<script lang="ts">
|
|
|
2 |
import { type NodeProps, useSvelteFlow } from '@xyflow/svelte';
|
3 |
import LynxKiteNode from './LynxKiteNode.svelte';
|
4 |
import NodeParameter from './NodeParameter.svelte';
|
|
|
6 |
export let id: $$Props['id'];
|
7 |
export let data: $$Props['data'];
|
8 |
const { updateNodeData } = useSvelteFlow();
|
9 |
+
$: metaParams = data.meta?.params;
|
|
|
10 |
</script>
|
11 |
|
12 |
<LynxKiteNode {...$$props} sourcePosition="top" targetPosition="bottom">
|