diff --git a/web/package-lock.json b/web/package-lock.json index 02e8acf40bc..b15d7a62e34 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -22,6 +22,7 @@ "human-id": "^4.1.1", "i18next": "^23.7.16", "i18next-browser-languagedetector": "^8.0.0", + "immer": "^10.1.1", "js-base64": "^3.7.5", "jsencrypt": "^3.3.2", "lodash": "^4.17.21", @@ -13635,8 +13636,6 @@ "version": "10.1.1", "resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz", "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", - "optional": true, - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" diff --git a/web/package.json b/web/package.json index 65a48a9a47a..493d077bd0a 100644 --- a/web/package.json +++ b/web/package.json @@ -33,6 +33,7 @@ "human-id": "^4.1.1", "i18next": "^23.7.16", "i18next-browser-languagedetector": "^8.0.0", + "immer": "^10.1.1", "js-base64": "^3.7.5", "jsencrypt": "^3.3.2", "lodash": "^4.17.21", diff --git a/web/src/locales/zh-traditional.ts b/web/src/locales/zh-traditional.ts index 5a7fd4c67f2..fea2c1bd07b 100644 --- a/web/src/locales/zh-traditional.ts +++ b/web/src/locales/zh-traditional.ts @@ -517,7 +517,7 @@ export default { messagePlaceholder: '訊息', messageMsg: '請輸入訊息或刪除此欄位。', addField: '新增字段', - loop: '環', + loop: '循環上限', createFlow: '创建工作流', yes: '是', no: '否', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index a4562ada6cb..5cfefef5eb0 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -536,7 +536,7 @@ export default { messagePlaceholder: '消息', messageMsg: '请输入消息或删除此字段。', addField: '新增字段', - loop: '环', + loop: '循环上限', createFlow: '创建工作流', yes: '是', no: '否', diff --git a/web/src/pages/flow/canvas/node/categorize-node.tsx b/web/src/pages/flow/canvas/node/categorize-node.tsx index c3c238f4d60..d81d85214d4 100644 --- a/web/src/pages/flow/canvas/node/categorize-node.tsx +++ b/web/src/pages/flow/canvas/node/categorize-node.tsx @@ -49,15 +49,18 @@ export function CategorizeNode({ id, data, selected }: NodeProps) { className={styles.handle} id={'c'} > - {Object.keys(categoryData).map((x, idx) => ( - - ))} + {Object.keys(categoryData).map((x, idx) => { + console.info(categoryData, id, data); + return ( + + ); + })} void; setEdges: (edges: Edge[]) => void; - updateNodeForm: (nodeId: string, values: any) => void; + updateNodeForm: (nodeId: string, values: any, path?: string[]) => void; onSelectionChange: OnSelectionChangeFunc; addNode: (nodes: Node) => void; getNode: (id?: string | null) => Node | undefined; @@ -55,7 +56,7 @@ export type RFState = { // this is our useStore hook that we can use in our components to get parts of the store and call actions const useGraphStore = create()( devtools( - (set, get) => ({ + immer((set, get) => ({ nodes: [] as Node[], edges: [] as Edge[], selectedNodeIds: [] as string[], @@ -108,6 +109,8 @@ const useGraphStore = create()( edges: addEdge(connection, get().edges), }); get().deletePreviousEdgeOfClassificationNode(connection); + // TODO: This may not be reasonable. You need to choose between listening to changes in the form. + get().updateFormDataOnConnect(connection); }, getEdge: (id: string) => { return get().edges.find((x) => x.id === id); @@ -115,8 +118,23 @@ const useGraphStore = create()( updateFormDataOnConnect: (connection: Connection) => { const { getOperatorTypeFromId, updateNodeForm } = get(); const { source, target, sourceHandle } = connection; - if (source && getOperatorTypeFromId(source) === Operator.Relevant) { - updateNodeForm(source, { [sourceHandle as string]: target }); + const operatorType = getOperatorTypeFromId(source); + if (source) { + switch (operatorType) { + case Operator.Relevant: + updateNodeForm(source, { [sourceHandle as string]: target }); + break; + case Operator.Categorize: + if (sourceHandle) + updateNodeForm(source, target, [ + 'category_description', + sourceHandle, + 'to', + ]); + break; + default: + break; + } } }, deletePreviousEdgeOfClassificationNode: (connection: Connection) => { @@ -166,13 +184,30 @@ const useGraphStore = create()( }); }, deleteEdgeById: (id: string) => { - const { edges, updateNodeForm } = get(); + const { edges, updateNodeForm, getOperatorTypeFromId } = get(); const currentEdge = edges.find((x) => x.id === id); + if (currentEdge) { + const { source, sourceHandle } = currentEdge; + const operatorType = getOperatorTypeFromId(source); // After deleting the edge, set the corresponding field in the node's form field to undefined - updateNodeForm(currentEdge.source, { - [currentEdge.sourceHandle as string]: undefined, - }); + switch (operatorType) { + case Operator.Relevant: + updateNodeForm(source, { + [sourceHandle as string]: undefined, + }); + break; + case Operator.Categorize: + if (sourceHandle) + updateNodeForm(source, undefined, [ + 'category_description', + sourceHandle, + 'to', + ]); + break; + default: + break; + } } set({ edges: edges.filter((edge) => edge.id !== id), @@ -203,7 +238,7 @@ const useGraphStore = create()( findNodeByName: (name: Operator) => { return get().nodes.find((x) => x.data.label === name); }, - updateNodeForm: (nodeId: string, values: any) => { + updateNodeForm: (nodeId: string, values: any, path: string[] = []) => { set({ nodes: get().nodes.map((node) => { if (node.id === nodeId) { @@ -211,11 +246,17 @@ const useGraphStore = create()( // ...node.data, // form: { ...node.data.form, ...values }, // }; + let nextForm: Record = { ...node.data.form }; + if (path.length === 0) { + nextForm = Object.assign(nextForm, values); + } else { + lodashSet(nextForm, path, values); + } return { ...node, data: { ...node.data, - form: { ...node.data.form, ...values }, + form: nextForm, }, } as any; } @@ -247,7 +288,7 @@ const useGraphStore = create()( setClickedNodeId: (id?: string) => { set({ clickedNodeId: id }); }, - }), + })), { name: 'graph' }, ), );