diff --git a/public/locales/en.json b/public/locales/en.json index f71fdfb..f187f52 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -79,6 +79,7 @@ "tree.desc": "Tree desc", "tree.export": "Export", "tree.firstid": "First id", + "tree.group": "Available groups", "tree.vars": "Define Variables", "tree.vars.name": "name", "tree.vars.invalidName": "Invalid variable name", diff --git a/public/locales/zh.json b/public/locales/zh.json index 8358596..9294f43 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -79,6 +79,7 @@ "tree.desc": "说明", "tree.export": "导出", "tree.firstid": "起始标识", + "tree.group": "可用分组", "tree.vars": "定义变量", "tree.vars.name": "变量名", "tree.vars.invalidName": "变量名不合法", diff --git a/sample/vars/test-vars.json b/sample/vars/test-vars.json index 78f4dae..9e4587b 100644 --- a/sample/vars/test-vars.json +++ b/sample/vars/test-vars.json @@ -3,6 +3,9 @@ "desc": "", "firstid": 1, "export": true, + "group": [ + "Client" + ], "declare": { "imports": [ "vars/declare-core.json", diff --git a/src/components/editor.tsx b/src/components/editor.tsx index 20f1fc3..f128142 100644 --- a/src/components/editor.tsx +++ b/src/components/editor.tsx @@ -171,6 +171,7 @@ export const Editor: FC = ({ onUpdate: updateState, data: editor, . workdir: state.workdir, relative: state.relative, updateFileMeta: state.updateFileMeta, + nodeDefs: state.nodeDefs, })) ); @@ -479,7 +480,7 @@ export const Editor: FC = ({ onUpdate: updateState, data: editor, . return; } b3util.copyFromNode(data, newNode); - data.def = b3util.getNodeDefs().get(data.name)!; + data.def = workspace.nodeDefs.get(data.name)!; data.size = calcTreeDataSize(data); if (oldNode.path !== newNode.path) { refresh(); @@ -497,6 +498,7 @@ export const Editor: FC = ({ onUpdate: updateState, data: editor, . if (editor.desc !== editTree.data.desc || editor.export !== editTree.data.export) { editor.desc = editTree.data.desc || ""; editor.export = editTree.data.export !== false; + editor.group = editTree.data.group || []; if (editor.data.firstid !== editTree.data.firstid) { editor.firstid = editTree.data.firstid ?? 1; editor.declare.vars = editTree.data.declare.vars || []; @@ -726,6 +728,7 @@ export const Editor: FC = ({ onUpdate: updateState, data: editor, . desc: editor.desc, firstid: editor.firstid ?? 1, export: editor.export, + group: editor.group ?? [], declare: { imports: editor.declare.imports.map((v) => v.path).sort(), vars: editor.declare.vars.sort((a, b) => a.name.localeCompare(b.name)), diff --git a/src/components/inspector.tsx b/src/components/inspector.tsx index 23c3ec9..df1241c 100644 --- a/src/components/inspector.tsx +++ b/src/components/inspector.tsx @@ -2,6 +2,7 @@ import { AimOutlined, EditOutlined, MinusCircleOutlined, PlusOutlined } from "@a import { AutoComplete, Button, + Checkbox, Divider, Flex, Form, @@ -20,6 +21,7 @@ import { useDebounceCallback } from "usehooks-ts"; import { useShallow } from "zustand/react/shallow"; import { EditNode, EditTree, useWorkspace } from "../contexts/workspace-context"; import { + GroupDef, ImportDef, isBoolType, isEnumType, @@ -57,24 +59,19 @@ const TreeInspector: FC = () => { allFiles: state.allFiles, relative: state.relative, fileTree: state.fileTree, + groupDefs: state.groupDefs, })) ); const { t } = useTranslation(); const [form] = Form.useForm(); - // set form values - useEffect(() => { - const data = workspace.editingTree.data; - loadVarDef(data.declare.imports); - form.resetFields(); - form.setFieldValue("name", data.name); - form.setFieldValue("desc", data.desc); - form.setFieldValue("export", data.export !== false); - form.setFieldValue("firstid", data.firstid); - form.setFieldValue("declare.vars", data.declare?.vars); - form.setFieldValue("declare.imports", data.declare?.imports); - form.setFieldValue("declare.subtree", data.declare?.subtree); - }, [workspace.editingTree]); + // group defs + const groupDefs: GroupDef[] = useMemo(() => { + return workspace.groupDefs.map((v) => ({ + name: v, + value: workspace.editingTree.data.group.includes(v), + })); + }, [workspace.groupDefs, workspace.editingTree]); // auto complete for subtree const subtreeOptions = useMemo(() => { @@ -91,6 +88,21 @@ const TreeInspector: FC = () => { return options; }, [workspace.allFiles, workspace.fileTree]); + // set form values + useEffect(() => { + const data = workspace.editingTree.data; + loadVarDef(data.declare.imports); + form.resetFields(); + form.setFieldValue("name", data.name); + form.setFieldValue("desc", data.desc); + form.setFieldValue("export", data.export !== false); + form.setFieldValue("firstid", data.firstid); + form.setFieldValue("group", groupDefs); + form.setFieldValue("declare.vars", data.declare?.vars); + form.setFieldValue("declare.imports", data.declare?.imports); + form.setFieldValue("declare.subtree", data.declare?.subtree); + }, [workspace.editingTree, groupDefs]); + const finish = (values: any) => { workspace.editing?.dispatch("updateTree", { data: { @@ -98,6 +110,10 @@ const TreeInspector: FC = () => { desc: values.desc || undefined, export: values.export, firstid: Number(values.firstid), + group: (values.group as GroupDef[]) + .map((v) => (v.value ? v.name : undefined)) + .filter((v) => v) + .sort(), declare: { vars: (values["declare.vars"] as VarDef[]) .filter((v) => v && v.name) @@ -143,6 +159,39 @@ const TreeInspector: FC = () => { form.submit()} /> + {groupDefs.length > 0 && ( + <> + +

{t("tree.group")}

+
+ + {(items) => ( + + {items + .filter((v) => groupDefs[v.name]) + .map((item, idx) => ( + + {groupDefs[idx].name} + + ))} + + )} + + + )} <>

{t("tree.vars")}

diff --git a/src/contexts/workspace-context.ts b/src/contexts/workspace-context.ts index 2b0eca6..faea9f9 100644 --- a/src/contexts/workspace-context.ts +++ b/src/contexts/workspace-context.ts @@ -49,6 +49,7 @@ export class EditorStore { export: boolean; name: string; firstid: number; + group: string[]; declare: { imports: ImportDef[]; @@ -85,6 +86,7 @@ export class EditorStore { this.export = file.export !== false; this.name = file.name || path.slice(0, -5); this.firstid = file.firstid ?? 1; + this.group = file.group ?? []; this.declare = { vars: file.declare?.vars ?? [], imports: @@ -126,6 +128,7 @@ export type EditTree = { desc?: string; export?: boolean; firstid?: number; + group: string[]; declare: { imports: ImportDef[]; vars: VarDef[]; @@ -183,6 +186,7 @@ export type WorkspaceStore = { loadNodeDefs: () => void; nodeDefs: b3util.NodeDefs; + groupDefs: string[]; // edit node editingNode?: EditNode | null; @@ -520,6 +524,7 @@ export const useWorkspace = create((set, get) => ({ name: editting.name, desc: editting.desc, firstid: editting.firstid, + group: editting.group, declare: { vars: editting.declare.vars, imports: editting.declare.imports, @@ -642,10 +647,11 @@ export const useWorkspace = create((set, get) => ({ }, nodeDefs: new b3util.NodeDefs(), + groupDefs: [], loadNodeDefs: () => { const workspace = get(); b3util.initWorkdir(workspace.workdir, message.error.bind(message)); - set({ nodeDefs: b3util.getNodeDefs() }); + set({ nodeDefs: b3util.getNodeDefs(), groupDefs: b3util.getGroupDefs() }); workspace.editing?.dispatch("refresh"); }, @@ -679,6 +685,7 @@ export const useWorkspace = create((set, get) => ({ desc: editor.desc, export: editor.export, firstid: editor.firstid, + group: editor.group, declare: { imports: editor.declare.imports, vars: editor.declare.vars, diff --git a/src/misc/b3type.ts b/src/misc/b3type.ts index bc419ef..04c14d8 100644 --- a/src/misc/b3type.ts +++ b/src/misc/b3type.ts @@ -30,6 +30,11 @@ export interface VarDef { desc: string; } +export interface GroupDef { + name: string; + value: boolean; +} + export interface ImportDef { path: string; date?: number; @@ -41,11 +46,12 @@ export interface TreeModel { desc?: string; export?: boolean; firstid?: number; - root: NodeModel; + group?: string[]; declare?: { imports?: string[]; vars?: VarDef[]; }; + root: NodeModel; } export interface TreeGraphData extends G6TreeGraphData { diff --git a/src/misc/b3util.ts b/src/misc/b3util.ts index 3786613..80226f5 100644 --- a/src/misc/b3util.ts +++ b/src/misc/b3util.ts @@ -27,6 +27,7 @@ export class NodeDefs extends Map { let workdir: string = ""; let alertError: (msg: string, duration?: number) => void = () => {}; let nodeDefs: NodeDefs = new NodeDefs(); +let groupDefs: string[] = []; const unknownNodeDef: NodeDef = { name: "unknown", @@ -38,14 +39,25 @@ export const getNodeDefs = () => { return nodeDefs; }; +export const getGroupDefs = () => { + return groupDefs; +}; + export const initWorkdir = (path: string, handler: typeof alertError) => { workdir = path; alertError = handler; const nodeDefData = readJson(`${workdir}/node-config.b3-setting`) as NodeDef[]; + const groups: Set = new Set(); nodeDefs = new NodeDefs(); for (const v of nodeDefData) { nodeDefs.set(v.name, v); + + const group = v.type.match(/\((\w+)\)/)?.[1]; + if (group) { + groups.add(group); + } } + groupDefs = Array.from(groups); }; export const isValidVariableName = (name: string) => {