add node def inspector
This commit is contained in:
1 parent
f8d04581d1
commit
47c058a831
4 files changed
+365
-300
No files matched your search
@@ -105,8 +105,6 @@ const renameFile = (oldPath: string, newPath: string) => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSvgIcon = (path: string) => {};
|
|
||||||
|
|
||||||
export const Explorer: FC = () => {
|
export const Explorer: FC = () => {
|
||||||
const workspace = {
|
const workspace = {
|
||||||
close: useWorkspace((state) => state.close),
|
close: useWorkspace((state) => state.close),
|
||||||
@@ -116,6 +114,7 @@ export const Explorer: FC = () => {
|
|||||||
nodeDefs: useWorkspace((state) => state.nodeDefs),
|
nodeDefs: useWorkspace((state) => state.nodeDefs),
|
||||||
nodeTree: useWorkspace((state) => state.nodeTree),
|
nodeTree: useWorkspace((state) => state.nodeTree),
|
||||||
workdir: useWorkspace((state) => state.workdir),
|
workdir: useWorkspace((state) => state.workdir),
|
||||||
|
onEditingNodeDef: useWorkspace((state) => state.onEditingNodeDef),
|
||||||
open: useWorkspace((state) => state.open),
|
open: useWorkspace((state) => state.open),
|
||||||
};
|
};
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -798,6 +797,14 @@ export const Explorer: FC = () => {
|
|||||||
fieldNames={{ key: "title" }}
|
fieldNames={{ key: "title" }}
|
||||||
treeData={workspace.nodeTree ? [workspace.nodeTree] : []}
|
treeData={workspace.nodeTree ? [workspace.nodeTree] : []}
|
||||||
draggable={{ icon: false, nodeDraggable: (node) => !!node.isLeaf }}
|
draggable={{ icon: false, nodeDraggable: (node) => !!node.isLeaf }}
|
||||||
|
onSelect={(_, info) => {
|
||||||
|
const node = info.node;
|
||||||
|
if (node && node.isLeaf) {
|
||||||
|
workspace.onEditingNodeDef({
|
||||||
|
data: node.def!,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
onDragStart={(e) => {
|
onDragStart={(e) => {
|
||||||
e.event.dataTransfer.setData("explore-node", e.node.def?.name ?? "");
|
e.event.dataTransfer.setData("explore-node", e.node.def?.name ?? "");
|
||||||
}}
|
}}
|
||||||
|
|||||||
+340
-283
@@ -10,11 +10,60 @@ import Markdown from "react-markdown";
|
|||||||
|
|
||||||
interface OptionType extends DefaultOptionType {}
|
interface OptionType extends DefaultOptionType {}
|
||||||
|
|
||||||
export const Inspector: FC = () => {
|
const TreeInspector: FC = () => {
|
||||||
const workspace = {
|
const workspace = {
|
||||||
editing: useWorkspace((state) => state.editing),
|
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 (
|
||||||
|
<>
|
||||||
|
<div style={{ padding: "12px 24px" }}>
|
||||||
|
<span style={{ fontSize: "18px", fontWeight: "600" }}>{t("tree.overview")}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={isMacos ? undefined : "b3-overflow"}
|
||||||
|
style={{ overflow: "auto", height: "100%", padding: "24px" }}
|
||||||
|
>
|
||||||
|
<Form form={form} labelCol={{ span: 8 }} onFinish={finish}>
|
||||||
|
<Form.Item name="name" label={t("tree.name")}>
|
||||||
|
<Input disabled={true} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="desc" label={t("tree.desc")}>
|
||||||
|
<Input onBlur={form.submit} />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const NodeInspector: FC = () => {
|
||||||
|
const workspace = {
|
||||||
|
editing: useWorkspace((state) => state.editing),
|
||||||
|
editingNode: useWorkspace((state) => state.editingNode)!,
|
||||||
getNodeDef: useWorkspace((state) => state.getNodeDef),
|
getNodeDef: useWorkspace((state) => state.getNodeDef),
|
||||||
nodeDefs: useWorkspace((state) => state.nodeDefs),
|
nodeDefs: useWorkspace((state) => state.nodeDefs),
|
||||||
onEditingNode: useWorkspace((state) => state.onEditingNode),
|
onEditingNode: useWorkspace((state) => state.onEditingNode),
|
||||||
@@ -26,31 +75,24 @@ export const Inspector: FC = () => {
|
|||||||
|
|
||||||
// set form values
|
// set form values
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace.editingTree) {
|
const data = workspace.editingNode.data;
|
||||||
const data = workspace.editingTree.data;
|
const def = workspace.getNodeDef(workspace.editingNode.data.name);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
form.setFieldValue("name", data.name);
|
form.setFieldValue("id", data.id);
|
||||||
form.setFieldValue("desc", data.desc);
|
form.setFieldValue("name", data.name);
|
||||||
} else if (workspace.editingNode) {
|
form.setFieldValue("desc", data.desc);
|
||||||
const data = workspace.editingNode.data;
|
form.setFieldValue("debug", data.debug);
|
||||||
const def = workspace.getNodeDef(workspace.editingNode.data.name);
|
form.setFieldValue("path", data.path);
|
||||||
form.resetFields();
|
def.args?.forEach((v) => {
|
||||||
form.setFieldValue("id", data.id);
|
form.setFieldValue(`args.${v.name}`, data.args?.[v.name]);
|
||||||
form.setFieldValue("name", data.name);
|
});
|
||||||
form.setFieldValue("desc", data.desc);
|
def.input?.forEach((_, i) => {
|
||||||
form.setFieldValue("debug", data.debug);
|
form.setFieldValue(`input.${i}`, data.input?.[i]);
|
||||||
form.setFieldValue("path", data.path);
|
});
|
||||||
def.args?.forEach((v) => {
|
def.output?.forEach((_, i) => {
|
||||||
form.setFieldValue(`args.${v.name}`, data.args?.[v.name]);
|
form.setFieldValue(`output.${i}`, data.output?.[i]);
|
||||||
});
|
});
|
||||||
def.input?.forEach((_, i) => {
|
}, [workspace.editingNode]);
|
||||||
form.setFieldValue(`input.${i}`, data.input?.[i]);
|
|
||||||
});
|
|
||||||
def.output?.forEach((_, i) => {
|
|
||||||
form.setFieldValue(`output.${i}`, data.output?.[i]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [workspace.editingNode, workspace.editingTree]);
|
|
||||||
|
|
||||||
// auto complete for node
|
// auto complete for node
|
||||||
const nodeOptions = useMemo(() => {
|
const nodeOptions = useMemo(() => {
|
||||||
@@ -99,264 +141,279 @@ export const Inspector: FC = () => {
|
|||||||
return options;
|
return options;
|
||||||
}, [workspace.allFiles, workspace.fileTree]);
|
}, [workspace.allFiles, workspace.fileTree]);
|
||||||
|
|
||||||
if (workspace.editingTree) {
|
const editingNode = workspace.editingNode;
|
||||||
const finish = (values: any) => {
|
const def = workspace.getNodeDef(editingNode.data.name);
|
||||||
const data = {} as TreeModel;
|
const disabled = !editingNode.editable;
|
||||||
data.name = values.name;
|
|
||||||
data.desc = values.desc || undefined;
|
// update value
|
||||||
workspace.editing?.dispatch?.("updateTree", {
|
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: {
|
data: {
|
||||||
name: values.name,
|
id: editingNode.data.id,
|
||||||
desc: values.desc || undefined,
|
name: workspace.nodeDefs.get(newname)?.name ?? newname,
|
||||||
|
desc: editingNode.data.desc,
|
||||||
|
debug: editingNode.data.debug,
|
||||||
},
|
},
|
||||||
} as EditTree);
|
editable: editingNode.editable,
|
||||||
};
|
});
|
||||||
return (
|
finish(form.getFieldsValue());
|
||||||
<Flex className="b3-inspector" vertical style={{ height: "100%" }}>
|
} else {
|
||||||
<div style={{ padding: "12px 24px" }}>
|
form.submit();
|
||||||
<span style={{ fontSize: "18px", fontWeight: "600" }}>{t("tree.overview")}</span>
|
}
|
||||||
</div>
|
};
|
||||||
<div
|
|
||||||
className={isMacos ? undefined : "b3-overflow"}
|
const changeSubtree = () => {
|
||||||
style={{ overflow: "auto", height: "100%", padding: "24px" }}
|
if (form.getFieldValue("path") !== editingNode.data.path) {
|
||||||
|
finish(form.getFieldsValue());
|
||||||
|
} else {
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div style={{ padding: "12px 24px" }}>
|
||||||
|
<span style={{ fontSize: "18px", fontWeight: "600" }}>{def.desc}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={isMacos ? undefined : "b3-overflow"}
|
||||||
|
style={{ overflow: "auto", height: "100%", padding: "24px" }}
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
wrapperCol={{ span: "auto" }}
|
||||||
|
labelCol={{ span: "auto" }}
|
||||||
|
onFinish={finish}
|
||||||
>
|
>
|
||||||
<Form form={form} labelCol={{ span: 8 }} onFinish={finish}>
|
<Form.Item
|
||||||
<Form.Item name="name" label={t("tree.name")}>
|
name="id"
|
||||||
<Input disabled={true} />
|
label={
|
||||||
</Form.Item>
|
<div style={{ minWidth: "80px", justifyContent: "flex-end" }}>{t("node.id")}</div>
|
||||||
<Form.Item name="desc" label={t("tree.desc")}>
|
}
|
||||||
<Input onBlur={form.submit} />
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
} 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 (
|
|
||||||
<Flex className="b3-inspector" vertical style={{ height: "100%" }}>
|
|
||||||
<div style={{ padding: "12px 24px" }}>
|
|
||||||
<span style={{ fontSize: "18px", fontWeight: "600" }}>{def.desc}</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={isMacos ? undefined : "b3-overflow"}
|
|
||||||
style={{ overflow: "auto", height: "100%", padding: "24px" }}
|
|
||||||
>
|
|
||||||
<Form
|
|
||||||
form={form}
|
|
||||||
wrapperCol={{ span: "auto" }}
|
|
||||||
labelCol={{ span: "auto" }}
|
|
||||||
onFinish={finish}
|
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Input disabled={true} />
|
||||||
name="id"
|
</Form.Item>
|
||||||
label={
|
<Form.Item label={t("node.name")} name="name">
|
||||||
<div style={{ minWidth: "80px", justifyContent: "flex-end" }}>{t("node.id")}</div>
|
<AutoComplete
|
||||||
}
|
disabled={disabled}
|
||||||
>
|
options={nodeOptions}
|
||||||
<Input disabled={true} />
|
onBlur={() => changeNodeDef(form.getFieldValue("name"))}
|
||||||
</Form.Item>
|
onSelect={changeNodeDef}
|
||||||
<Form.Item label={t("node.name")} name="name">
|
onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
|
||||||
<AutoComplete
|
filterOption={(inputValue: string, option?: OptionType) => {
|
||||||
disabled={disabled}
|
const label = option!.label as string;
|
||||||
options={nodeOptions}
|
return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
|
||||||
onBlur={() => changeNodeDef(form.getFieldValue("name"))}
|
}}
|
||||||
onSelect={changeNodeDef}
|
/>
|
||||||
onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
|
</Form.Item>
|
||||||
filterOption={(inputValue: string, option?: OptionType) => {
|
<Form.Item name="desc" label={t("node.desc")}>
|
||||||
const label = option!.label as string;
|
<Input disabled={disabled} onBlur={form.submit} />
|
||||||
return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
|
</Form.Item>
|
||||||
}}
|
<Form.Item label={t("node.debug")} name="debug" valuePropName="checked">
|
||||||
/>
|
<Switch disabled={disabled && !editingNode.data.path} onChange={form.submit} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="desc" label={t("node.desc")}>
|
<Form.Item label={t("node.subtree")} name="path">
|
||||||
<Input disabled={disabled} onBlur={form.submit} />
|
<AutoComplete
|
||||||
</Form.Item>
|
disabled={disabled && !editingNode.data.path}
|
||||||
<Form.Item label={t("node.debug")} name="debug" valuePropName="checked">
|
options={subtreeOptions}
|
||||||
<Switch disabled={disabled && !editingNode.data.path} onChange={form.submit} />
|
onBlur={changeSubtree}
|
||||||
</Form.Item>
|
onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
|
||||||
<Form.Item label={t("node.subtree")} name="path">
|
filterOption={(inputValue: string, option?: OptionType) => {
|
||||||
<AutoComplete
|
const label = option!.label as string;
|
||||||
disabled={disabled && !editingNode.data.path}
|
return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
|
||||||
options={subtreeOptions}
|
}}
|
||||||
onBlur={changeSubtree}
|
/>
|
||||||
onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
|
</Form.Item>
|
||||||
filterOption={(inputValue: string, option?: OptionType) => {
|
<Markdown>{def.doc}</Markdown>
|
||||||
const label = option!.label as string;
|
{def.input && def.input.length > 0 && (
|
||||||
return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
|
<>
|
||||||
}}
|
<Divider orientation="left">
|
||||||
/>
|
<h4>{t("node.inputVariable")}</h4>
|
||||||
</Form.Item>
|
</Divider>
|
||||||
<Markdown>{def.doc}</Markdown>
|
{def.input.map((v, i) => {
|
||||||
{def.input && def.input.length > 0 && (
|
const required = v.indexOf("?") == -1;
|
||||||
<>
|
const desc = v.replace("?", "");
|
||||||
<Divider orientation="left">
|
return (
|
||||||
<h4>{t("node.inputVariable")}</h4>
|
<Form.Item
|
||||||
</Divider>
|
label={desc}
|
||||||
{def.input.map((v, i) => {
|
name={`input.${i}`}
|
||||||
const required = v.indexOf("?") == -1;
|
key={`input.${i}`}
|
||||||
const desc = v.replace("?", "");
|
rules={[{ required, message: t("node.fileRequired", { field: desc }) }]}
|
||||||
return (
|
>
|
||||||
<Form.Item
|
<AutoComplete
|
||||||
label={desc}
|
disabled={disabled}
|
||||||
name={`input.${i}`}
|
options={inoutVarOptions}
|
||||||
key={`input.${i}`}
|
onBlur={form.submit}
|
||||||
rules={[{ required, message: t("node.fileRequired", { field: desc }) }]}
|
onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
|
||||||
>
|
filterOption={(inputValue: string, option?: OptionType) => {
|
||||||
<AutoComplete
|
const label = option!.label as string;
|
||||||
disabled={disabled}
|
return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
|
||||||
options={inoutVarOptions}
|
}}
|
||||||
onBlur={form.submit}
|
/>
|
||||||
onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
|
</Form.Item>
|
||||||
filterOption={(inputValue: string, option?: OptionType) => {
|
);
|
||||||
const label = option!.label as string;
|
})}
|
||||||
return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
|
</>
|
||||||
}}
|
)}
|
||||||
/>
|
{def.args && def.args.length > 0 && (
|
||||||
</Form.Item>
|
<>
|
||||||
);
|
<Divider orientation="left">
|
||||||
})}
|
<h4>{t("node.args")}</h4>
|
||||||
</>
|
</Divider>
|
||||||
)}
|
{def.args.map((v) => {
|
||||||
{def.args && def.args.length > 0 && (
|
const required = v.type.indexOf("?") == -1;
|
||||||
<>
|
const type = v.type.replace("?", "") as NodeArgType;
|
||||||
<Divider orientation="left">
|
return (
|
||||||
<h4>{t("node.args")}</h4>
|
<Form.Item
|
||||||
</Divider>
|
name={`args.${v.name}`}
|
||||||
{def.args.map((v) => {
|
label={v.desc}
|
||||||
const required = v.type.indexOf("?") == -1;
|
key={`args.${v.name}`}
|
||||||
const type = v.type.replace("?", "") as NodeArgType;
|
initialValue={type === "boolean" ? v.default ?? false : v.default}
|
||||||
return (
|
valuePropName={type === "boolean" ? "checked" : undefined}
|
||||||
<Form.Item
|
rules={[{ required, message: t("node.fileRequired", { field: v.desc }) }]}
|
||||||
name={`args.${v.name}`}
|
>
|
||||||
label={v.desc}
|
{type === "string" && <Input disabled={disabled} onBlur={form.submit} />}
|
||||||
key={`args.${v.name}`}
|
{type === "int" && (
|
||||||
initialValue={type === "boolean" ? v.default ?? false : v.default}
|
<InputNumber disabled={disabled} onBlur={form.submit} precision={0} />
|
||||||
valuePropName={type === "boolean" ? "checked" : undefined}
|
)}
|
||||||
rules={[{ required, message: t("node.fileRequired", { field: v.desc }) }]}
|
{type === "float" && <InputNumber disabled={disabled} onBlur={form.submit} />}
|
||||||
>
|
{type === "boolean" && <Switch disabled={disabled} onChange={form.submit} />}
|
||||||
{type === "string" && <Input disabled={disabled} onBlur={form.submit} />}
|
{type === "code" && (
|
||||||
{type === "int" && (
|
<Input onBlur={form.submit} placeholder={t("node.codePlaceholder")} />
|
||||||
<InputNumber disabled={disabled} onBlur={form.submit} precision={0} />
|
)}
|
||||||
)}
|
{type === "enum" && (
|
||||||
{type === "float" && <InputNumber disabled={disabled} onBlur={form.submit} />}
|
<Select disabled={disabled} onBlur={form.submit} onChange={form.submit}>
|
||||||
{type === "boolean" && <Switch disabled={disabled} onChange={form.submit} />}
|
{v.options?.map((value) => {
|
||||||
{type === "code" && (
|
return (
|
||||||
<Input onBlur={form.submit} placeholder={t("node.codePlaceholder")} />
|
<Select.Option key={value.name} value={value.value}>
|
||||||
)}
|
{value.name}
|
||||||
{type === "enum" && (
|
</Select.Option>
|
||||||
<Select disabled={disabled} onBlur={form.submit} onChange={form.submit}>
|
);
|
||||||
{v.options?.map((value) => {
|
})}
|
||||||
return (
|
</Select>
|
||||||
<Select.Option key={value.name} value={value.value}>
|
)}
|
||||||
{value.name}
|
</Form.Item>
|
||||||
</Select.Option>
|
);
|
||||||
);
|
})}
|
||||||
})}
|
</>
|
||||||
</Select>
|
)}
|
||||||
)}
|
{def.output && def.output.length > 0 && (
|
||||||
</Form.Item>
|
<>
|
||||||
);
|
<Divider orientation="left">
|
||||||
})}
|
<h4>{t("node.outputVariable")}</h4>
|
||||||
</>
|
</Divider>
|
||||||
)}
|
{def.output.map((v, i) => {
|
||||||
{def.output && def.output.length > 0 && (
|
const required = v.indexOf("?") == -1;
|
||||||
<>
|
const desc = v.replace("?", "");
|
||||||
<Divider orientation="left">
|
return (
|
||||||
<h4>{t("node.outputVariable")}</h4>
|
<Form.Item
|
||||||
</Divider>
|
label={desc}
|
||||||
{def.output.map((v, i) => {
|
name={`output.${i}`}
|
||||||
const required = v.indexOf("?") == -1;
|
key={`output.${i}`}
|
||||||
const desc = v.replace("?", "");
|
rules={[{ required, message: t("node.fileRequired", { field: desc }) }]}
|
||||||
return (
|
>
|
||||||
<Form.Item
|
<AutoComplete
|
||||||
label={desc}
|
disabled={disabled}
|
||||||
name={`output.${i}`}
|
options={inoutVarOptions}
|
||||||
key={`output.${i}`}
|
onBlur={form.submit}
|
||||||
rules={[{ required, message: t("node.fileRequired", { field: desc }) }]}
|
onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
|
||||||
>
|
filterOption={(inputValue: string, option?: OptionType) => {
|
||||||
<AutoComplete
|
const label = option!.label as string;
|
||||||
disabled={disabled}
|
return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
|
||||||
options={inoutVarOptions}
|
}}
|
||||||
onBlur={form.submit}
|
/>
|
||||||
onInputKeyDown={(e) => e.code === Hotkey.Escape && e.preventDefault()}
|
</Form.Item>
|
||||||
filterOption={(inputValue: string, option?: OptionType) => {
|
);
|
||||||
const label = option!.label as string;
|
})}
|
||||||
return label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1;
|
</>
|
||||||
}}
|
)}
|
||||||
/>
|
</Form>
|
||||||
</Form.Item>
|
</div>
|
||||||
);
|
</>
|
||||||
})}
|
);
|
||||||
</>
|
};
|
||||||
)}
|
|
||||||
</Form>
|
const NodeDefInspector: FC = () => {
|
||||||
</div>
|
const [form] = Form.useForm();
|
||||||
</Flex>
|
return (
|
||||||
);
|
<>
|
||||||
} else {
|
<div style={{ padding: "12px 24px" }}>
|
||||||
return null;
|
<span style={{ fontSize: "18px", fontWeight: "600" }}>Node Definition</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={isMacos ? undefined : "b3-overflow"}
|
||||||
|
style={{ overflow: "auto", height: "100%", padding: "24px" }}
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
wrapperCol={{ span: "auto" }}
|
||||||
|
labelCol={{ span: "auto" }}
|
||||||
|
// onFinish={finish}
|
||||||
|
></Form>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<Flex
|
||||||
|
vertical
|
||||||
|
className="b3-inspector"
|
||||||
|
style={{ height: "100%", width: "340px", borderLeft: `1px solid var(--b3-color-border)` }}
|
||||||
|
>
|
||||||
|
{isEditingNodeDef && <NodeDefInspector />}
|
||||||
|
{isEditingTree && <TreeInspector />}
|
||||||
|
{isEditingNode && <NodeInspector />}
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
@@ -409,18 +409,7 @@ export const Workspace: FC = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Content>
|
</Content>
|
||||||
{workspace.editors.length > 0 && (
|
<Inspector />
|
||||||
<Sider
|
|
||||||
className="b3-inspector-wrapper"
|
|
||||||
width={340}
|
|
||||||
style={{
|
|
||||||
height: "100%",
|
|
||||||
borderLeft: `1px solid var(--b3-color-border)`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Inspector />
|
|
||||||
</Sider>
|
|
||||||
)}
|
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ export type EditNode = {
|
|||||||
editable: boolean;
|
editable: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EditNodeDef = {
|
||||||
|
data: NodeDef;
|
||||||
|
};
|
||||||
|
|
||||||
export type EditTree = {
|
export type EditTree = {
|
||||||
data: TreeModel;
|
data: TreeModel;
|
||||||
};
|
};
|
||||||
@@ -133,6 +137,10 @@ export type WorkspaceStore = {
|
|||||||
editingNode?: EditNode | null;
|
editingNode?: EditNode | null;
|
||||||
onEditingNode: (node: EditNode) => void;
|
onEditingNode: (node: EditNode) => void;
|
||||||
|
|
||||||
|
// edit node def
|
||||||
|
editingNodeDef?: EditNodeDef | null;
|
||||||
|
onEditingNodeDef: (node: EditNodeDef) => void;
|
||||||
|
|
||||||
// edit tree
|
// edit tree
|
||||||
editingTree?: EditTree | null;
|
editingTree?: EditTree | null;
|
||||||
onEditingTree: (tree: EditTree | null) => void;
|
onEditingTree: (tree: EditTree | null) => void;
|
||||||
@@ -373,7 +381,7 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ({
|
|||||||
}
|
}
|
||||||
if (editors.length === 0) {
|
if (editors.length === 0) {
|
||||||
editting = undefined;
|
editting = undefined;
|
||||||
set({ editingNode: undefined });
|
set({ editingNode: undefined, editingTree: undefined });
|
||||||
}
|
}
|
||||||
set({ editing: editting, editors: editors });
|
set({ editing: editting, editors: editors });
|
||||||
},
|
},
|
||||||
@@ -479,12 +487,16 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ({
|
|||||||
|
|
||||||
// node edit
|
// node edit
|
||||||
onEditingNode: (node) => {
|
onEditingNode: (node) => {
|
||||||
set({ editingNode: node });
|
set({ editingNode: node, editingNodeDef: null });
|
||||||
|
},
|
||||||
|
|
||||||
|
onEditingNodeDef: (nodeDef) => {
|
||||||
|
set({ editingNodeDef: nodeDef });
|
||||||
},
|
},
|
||||||
|
|
||||||
// tree edit
|
// tree edit
|
||||||
onEditingTree: (tree) => {
|
onEditingTree: (tree) => {
|
||||||
set({ editingTree: tree });
|
set({ editingTree: tree, editingNodeDef: null });
|
||||||
},
|
},
|
||||||
|
|
||||||
// node def
|
// node def
|
||||||
|
|||||||
Reference in new issue
Block a user