diff --git a/src/components/explorer.tsx b/src/components/explorer.tsx
index 8c99f34..e73d3c8 100644
--- a/src/components/explorer.tsx
+++ b/src/components/explorer.tsx
@@ -105,8 +105,6 @@ const renameFile = (oldPath: string, newPath: string) => {
return false;
};
-const getSvgIcon = (path: string) => {};
-
export const Explorer: FC = () => {
const workspace = {
close: useWorkspace((state) => state.close),
@@ -116,6 +114,7 @@ export const Explorer: FC = () => {
nodeDefs: useWorkspace((state) => state.nodeDefs),
nodeTree: useWorkspace((state) => state.nodeTree),
workdir: useWorkspace((state) => state.workdir),
+ onEditingNodeDef: useWorkspace((state) => state.onEditingNodeDef),
open: useWorkspace((state) => state.open),
};
const { t } = useTranslation();
@@ -798,6 +797,14 @@ export const Explorer: FC = () => {
fieldNames={{ key: "title" }}
treeData={workspace.nodeTree ? [workspace.nodeTree] : []}
draggable={{ icon: false, nodeDraggable: (node) => !!node.isLeaf }}
+ onSelect={(_, info) => {
+ const node = info.node;
+ if (node && node.isLeaf) {
+ workspace.onEditingNodeDef({
+ data: node.def!,
+ });
+ }
+ }}
onDragStart={(e) => {
e.event.dataTransfer.setData("explore-node", e.node.def?.name ?? "");
}}
diff --git a/src/components/inspector.tsx b/src/components/inspector.tsx
index 13d6852..89fc64e 100644
--- a/src/components/inspector.tsx
+++ b/src/components/inspector.tsx
@@ -10,11 +10,60 @@ import Markdown from "react-markdown";
interface OptionType extends DefaultOptionType {}
-export const Inspector: FC = () => {
+const TreeInspector: FC = () => {
const workspace = {
editing: useWorkspace((state) => state.editing),
- editingNode: useWorkspace((state) => state.editingNode),
- editingTree: useWorkspace((state) => state.editingTree),
+ editingTree: useWorkspace((state) => state.editingTree)!,
+ };
+ const { t } = useTranslation();
+ const [form] = Form.useForm();
+
+ // set form values
+ useEffect(() => {
+ const data = workspace.editingTree.data;
+ form.resetFields();
+ form.setFieldValue("name", data.name);
+ form.setFieldValue("desc", data.desc);
+ }, [workspace.editingTree]);
+
+ const finish = (values: any) => {
+ const data = {} as TreeModel;
+ data.name = values.name;
+ data.desc = values.desc || undefined;
+ workspace.editing?.dispatch?.("updateTree", {
+ data: {
+ name: values.name,
+ desc: values.desc || undefined,
+ },
+ } as EditTree);
+ };
+
+ return (
+ <>
+
+ {t("tree.overview")}
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+const NodeInspector: FC = () => {
+ const workspace = {
+ editing: useWorkspace((state) => state.editing),
+ editingNode: useWorkspace((state) => state.editingNode)!,
getNodeDef: useWorkspace((state) => state.getNodeDef),
nodeDefs: useWorkspace((state) => state.nodeDefs),
onEditingNode: useWorkspace((state) => state.onEditingNode),
@@ -26,31 +75,24 @@ export const Inspector: FC = () => {
// set form values
useEffect(() => {
- if (workspace.editingTree) {
- const data = workspace.editingTree.data;
- form.resetFields();
- form.setFieldValue("name", data.name);
- form.setFieldValue("desc", data.desc);
- } else if (workspace.editingNode) {
- const data = workspace.editingNode.data;
- const def = workspace.getNodeDef(workspace.editingNode.data.name);
- form.resetFields();
- form.setFieldValue("id", data.id);
- form.setFieldValue("name", data.name);
- form.setFieldValue("desc", data.desc);
- form.setFieldValue("debug", data.debug);
- form.setFieldValue("path", data.path);
- def.args?.forEach((v) => {
- form.setFieldValue(`args.${v.name}`, data.args?.[v.name]);
- });
- def.input?.forEach((_, i) => {
- form.setFieldValue(`input.${i}`, data.input?.[i]);
- });
- def.output?.forEach((_, i) => {
- form.setFieldValue(`output.${i}`, data.output?.[i]);
- });
- }
- }, [workspace.editingNode, workspace.editingTree]);
+ const data = workspace.editingNode.data;
+ const def = workspace.getNodeDef(workspace.editingNode.data.name);
+ form.resetFields();
+ form.setFieldValue("id", data.id);
+ form.setFieldValue("name", data.name);
+ form.setFieldValue("desc", data.desc);
+ form.setFieldValue("debug", data.debug);
+ form.setFieldValue("path", data.path);
+ def.args?.forEach((v) => {
+ form.setFieldValue(`args.${v.name}`, data.args?.[v.name]);
+ });
+ def.input?.forEach((_, i) => {
+ form.setFieldValue(`input.${i}`, data.input?.[i]);
+ });
+ def.output?.forEach((_, i) => {
+ form.setFieldValue(`output.${i}`, data.output?.[i]);
+ });
+ }, [workspace.editingNode]);
// auto complete for node
const nodeOptions = useMemo(() => {
@@ -99,264 +141,279 @@ export const Inspector: FC = () => {
return options;
}, [workspace.allFiles, workspace.fileTree]);
- if (workspace.editingTree) {
- const finish = (values: any) => {
- const data = {} as TreeModel;
- data.name = values.name;
- data.desc = values.desc || undefined;
- workspace.editing?.dispatch?.("updateTree", {
+ const editingNode = workspace.editingNode;
+ const def = workspace.getNodeDef(editingNode.data.name);
+ const disabled = !editingNode.editable;
+
+ // update value
+ const finish = (values: any) => {
+ const data = {} as NodeModel;
+ data.id = editingNode.data.id;
+ data.name = values.name;
+ data.debug = values.debug || undefined;
+ data.desc = values.desc || undefined;
+ data.path = values.path || undefined;
+
+ def.args?.forEach((arg) => {
+ const v = values[`args.${arg.name}`];
+ if (v !== null && v !== undefined && v !== "") {
+ data.args ||= {};
+ data.args[arg.name] = v;
+ }
+ });
+
+ def.input?.forEach((_, i) => {
+ const v = values[`input.${i}`];
+ data.input ||= [];
+ data.input.push(v ?? "");
+ });
+
+ def.output?.forEach((_, i) => {
+ const v = values[`output.${i}`];
+ data.output ||= [];
+ data.output.push(v ?? "");
+ });
+ workspace.editing?.dispatch?.("updateNode", {
+ data: data,
+ } as EditNode);
+ };
+
+ // change node def
+ const changeNodeDef = (newname: string) => {
+ if (editingNode.data.name !== newname) {
+ workspace.onEditingNode({
data: {
- name: values.name,
- desc: values.desc || undefined,
+ id: editingNode.data.id,
+ name: workspace.nodeDefs.get(newname)?.name ?? newname,
+ desc: editingNode.data.desc,
+ debug: editingNode.data.debug,
},
- } as EditTree);
- };
- return (
-
-
- {t("tree.overview")}
-
- {
+ if (form.getFieldValue("path") !== editingNode.data.path) {
+ finish(form.getFieldsValue());
+ } else {
+ form.submit();
+ }
+ };
+
+ return (
+ <>
+
+ {def.desc}
+
+
+
-
-
-
-
-
-
-
-
- );
- } else if (workspace.editingNode) {
- const editingNode = workspace.editingNode;
- const def = workspace.getNodeDef(editingNode.data.name);
- const disabled = !editingNode.editable;
-
- // update value
- const finish = (values: any) => {
- const data = {} as NodeModel;
- data.id = editingNode.data.id;
- data.name = values.name;
- data.debug = values.debug || undefined;
- data.desc = values.desc || undefined;
- data.path = values.path || undefined;
-
- def.args?.forEach((arg) => {
- const v = values[`args.${arg.name}`];
- if (v !== null && v !== undefined && v !== "") {
- data.args ||= {};
- data.args[arg.name] = v;
- }
- });
-
- def.input?.forEach((_, i) => {
- const v = values[`input.${i}`];
- data.input ||= [];
- data.input.push(v ?? "");
- });
-
- def.output?.forEach((_, i) => {
- const v = values[`output.${i}`];
- data.output ||= [];
- data.output.push(v ?? "");
- });
- workspace.editing?.dispatch?.("updateNode", {
- data: data,
- } as EditNode);
- };
-
- // change node def
- const changeNodeDef = (newname: string) => {
- if (editingNode.data.name !== newname) {
- workspace.onEditingNode({
- data: {
- id: editingNode.data.id,
- name: workspace.nodeDefs.get(newname)?.name ?? newname,
- desc: editingNode.data.desc,
- debug: editingNode.data.debug,
- },
- editable: editingNode.editable,
- });
- finish(form.getFieldsValue());
- } else {
- form.submit();
- }
- };
-
- const changeSubtree = () => {
- if (form.getFieldValue("path") !== editingNode.data.path) {
- finish(form.getFieldsValue());
- } else {
- form.submit();
- }
- };
-
- return (
-
-
- {def.desc}
-
-
-
+ }
>
- {t("node.id")}
- }
- >
-
-
-
- changeNodeDef(form.getFieldValue("name"))}
- onSelect={changeNodeDef}
- onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
- filterOption={(inputValue: string, option?: OptionType) => {
- const label = option!.label as string;
- return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
- }}
- />
-
-
-
-
-
-
-
-
- e.code === Hotkey.Escape && e.preventDefault()}
- filterOption={(inputValue: string, option?: OptionType) => {
- const label = option!.label as string;
- return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
- }}
- />
-
- {def.doc}
- {def.input && def.input.length > 0 && (
- <>
-
- {t("node.inputVariable")}
-
- {def.input.map((v, i) => {
- const required = v.indexOf("?") == -1;
- const desc = v.replace("?", "");
- return (
-
- e.code === Hotkey.Escape && e.preventDefault()}
- filterOption={(inputValue: string, option?: OptionType) => {
- const label = option!.label as string;
- return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
- }}
- />
-
- );
- })}
- >
- )}
- {def.args && def.args.length > 0 && (
- <>
-
- {t("node.args")}
-
- {def.args.map((v) => {
- const required = v.type.indexOf("?") == -1;
- const type = v.type.replace("?", "") as NodeArgType;
- return (
-
- {type === "string" && }
- {type === "int" && (
-
- )}
- {type === "float" && }
- {type === "boolean" && }
- {type === "code" && (
-
- )}
- {type === "enum" && (
-
- )}
-
- );
- })}
- >
- )}
- {def.output && def.output.length > 0 && (
- <>
-
- {t("node.outputVariable")}
-
- {def.output.map((v, i) => {
- const required = v.indexOf("?") == -1;
- const desc = v.replace("?", "");
- return (
-
- e.code === Hotkey.Escape && e.preventDefault()}
- filterOption={(inputValue: string, option?: OptionType) => {
- const label = option!.label as string;
- return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
- }}
- />
-
- );
- })}
- >
- )}
-
-
-
- );
- } else {
- return null;
+
+
+
+ changeNodeDef(form.getFieldValue("name"))}
+ onSelect={changeNodeDef}
+ onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
+ filterOption={(inputValue: string, option?: OptionType) => {
+ const label = option!.label as string;
+ return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
+ }}
+ />
+
+
+
+
+
+
+
+
+ e.code === Hotkey.Escape && e.preventDefault()}
+ filterOption={(inputValue: string, option?: OptionType) => {
+ const label = option!.label as string;
+ return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
+ }}
+ />
+
+ {def.doc}
+ {def.input && def.input.length > 0 && (
+ <>
+
+ {t("node.inputVariable")}
+
+ {def.input.map((v, i) => {
+ const required = v.indexOf("?") == -1;
+ const desc = v.replace("?", "");
+ return (
+
+ e.code === Hotkey.Escape && e.preventDefault()}
+ filterOption={(inputValue: string, option?: OptionType) => {
+ const label = option!.label as string;
+ return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
+ }}
+ />
+
+ );
+ })}
+ >
+ )}
+ {def.args && def.args.length > 0 && (
+ <>
+
+ {t("node.args")}
+
+ {def.args.map((v) => {
+ const required = v.type.indexOf("?") == -1;
+ const type = v.type.replace("?", "") as NodeArgType;
+ return (
+
+ {type === "string" && }
+ {type === "int" && (
+
+ )}
+ {type === "float" && }
+ {type === "boolean" && }
+ {type === "code" && (
+
+ )}
+ {type === "enum" && (
+
+ )}
+
+ );
+ })}
+ >
+ )}
+ {def.output && def.output.length > 0 && (
+ <>
+
+ {t("node.outputVariable")}
+
+ {def.output.map((v, i) => {
+ const required = v.indexOf("?") == -1;
+ const desc = v.replace("?", "");
+ return (
+
+ e.code === Hotkey.Escape && e.preventDefault()}
+ filterOption={(inputValue: string, option?: OptionType) => {
+ const label = option!.label as string;
+ return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
+ }}
+ />
+
+ );
+ })}
+ >
+ )}
+
+
+ >
+ );
+};
+
+const NodeDefInspector: FC = () => {
+ const [form] = Form.useForm();
+ return (
+ <>
+
+ Node Definition
+
+
+
+
+ >
+ );
+};
+
+export const Inspector: FC = () => {
+ const workspace = {
+ editingNode: useWorkspace((state) => state.editingNode),
+ editingTree: useWorkspace((state) => state.editingTree),
+ editingNodeDef: useWorkspace((state) => state.editingNodeDef),
+ };
+ let isEditingNode = false;
+ let isEditingTree = false;
+ let isEditingNodeDef = false;
+ if (workspace.editingNodeDef) {
+ isEditingNodeDef = true;
+ } else if (workspace.editingTree) {
+ isEditingTree = true;
+ } else if (workspace.editingNode) {
+ isEditingNode = true;
}
+ return (
+
+ {isEditingNodeDef && }
+ {isEditingTree && }
+ {isEditingNode && }
+
+ );
};
diff --git a/src/components/workspace.tsx b/src/components/workspace.tsx
index f1a0d85..e1c173f 100644
--- a/src/components/workspace.tsx
+++ b/src/components/workspace.tsx
@@ -409,18 +409,7 @@ export const Workspace: FC = () => {
/>
)}
- {workspace.editors.length > 0 && (
-
-
-
- )}
+
);
diff --git a/src/contexts/workspace-context.ts b/src/contexts/workspace-context.ts
index f15c133..ed73e0d 100644
--- a/src/contexts/workspace-context.ts
+++ b/src/contexts/workspace-context.ts
@@ -93,6 +93,10 @@ export type EditNode = {
editable: boolean;
};
+export type EditNodeDef = {
+ data: NodeDef;
+};
+
export type EditTree = {
data: TreeModel;
};
@@ -133,6 +137,10 @@ export type WorkspaceStore = {
editingNode?: EditNode | null;
onEditingNode: (node: EditNode) => void;
+ // edit node def
+ editingNodeDef?: EditNodeDef | null;
+ onEditingNodeDef: (node: EditNodeDef) => void;
+
// edit tree
editingTree?: EditTree | null;
onEditingTree: (tree: EditTree | null) => void;
@@ -373,7 +381,7 @@ export const useWorkspace = create((set, get) => ({
}
if (editors.length === 0) {
editting = undefined;
- set({ editingNode: undefined });
+ set({ editingNode: undefined, editingTree: undefined });
}
set({ editing: editting, editors: editors });
},
@@ -479,12 +487,16 @@ export const useWorkspace = create((set, get) => ({
// node edit
onEditingNode: (node) => {
- set({ editingNode: node });
+ set({ editingNode: node, editingNodeDef: null });
+ },
+
+ onEditingNodeDef: (nodeDef) => {
+ set({ editingNodeDef: nodeDef });
},
// tree edit
onEditingTree: (tree) => {
- set({ editingTree: tree });
+ set({ editingTree: tree, editingNodeDef: null });
},
// node def