mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-14 12:25:52 +08:00
feat: when Categorize establishes a connection with other operators, it adds the target node to the to field. #918 (#1418)
### What problem does this PR solve? feat: when Categorize establishes a connection with other operators, it adds the target node to the to field. #918 feat: modify the Chinese text of loop #918 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
61557a101a
commit
fce3f6df8e
3
web/package-lock.json
generated
3
web/package-lock.json
generated
@ -22,6 +22,7 @@
|
|||||||
"human-id": "^4.1.1",
|
"human-id": "^4.1.1",
|
||||||
"i18next": "^23.7.16",
|
"i18next": "^23.7.16",
|
||||||
"i18next-browser-languagedetector": "^8.0.0",
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
|
"immer": "^10.1.1",
|
||||||
"js-base64": "^3.7.5",
|
"js-base64": "^3.7.5",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@ -13635,8 +13636,6 @@
|
|||||||
"version": "10.1.1",
|
"version": "10.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
||||||
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/immer"
|
"url": "https://opencollective.com/immer"
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"human-id": "^4.1.1",
|
"human-id": "^4.1.1",
|
||||||
"i18next": "^23.7.16",
|
"i18next": "^23.7.16",
|
||||||
"i18next-browser-languagedetector": "^8.0.0",
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
|
"immer": "^10.1.1",
|
||||||
"js-base64": "^3.7.5",
|
"js-base64": "^3.7.5",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@ -517,7 +517,7 @@ export default {
|
|||||||
messagePlaceholder: '訊息',
|
messagePlaceholder: '訊息',
|
||||||
messageMsg: '請輸入訊息或刪除此欄位。',
|
messageMsg: '請輸入訊息或刪除此欄位。',
|
||||||
addField: '新增字段',
|
addField: '新增字段',
|
||||||
loop: '環',
|
loop: '循環上限',
|
||||||
createFlow: '创建工作流',
|
createFlow: '创建工作流',
|
||||||
yes: '是',
|
yes: '是',
|
||||||
no: '否',
|
no: '否',
|
||||||
|
@ -536,7 +536,7 @@ export default {
|
|||||||
messagePlaceholder: '消息',
|
messagePlaceholder: '消息',
|
||||||
messageMsg: '请输入消息或删除此字段。',
|
messageMsg: '请输入消息或删除此字段。',
|
||||||
addField: '新增字段',
|
addField: '新增字段',
|
||||||
loop: '环',
|
loop: '循环上限',
|
||||||
createFlow: '创建工作流',
|
createFlow: '创建工作流',
|
||||||
yes: '是',
|
yes: '是',
|
||||||
no: '否',
|
no: '否',
|
||||||
|
@ -49,15 +49,18 @@ export function CategorizeNode({ id, data, selected }: NodeProps<NodeData>) {
|
|||||||
className={styles.handle}
|
className={styles.handle}
|
||||||
id={'c'}
|
id={'c'}
|
||||||
></Handle>
|
></Handle>
|
||||||
{Object.keys(categoryData).map((x, idx) => (
|
{Object.keys(categoryData).map((x, idx) => {
|
||||||
<CategorizeHandle
|
console.info(categoryData, id, data);
|
||||||
top={CategorizeAnchorPointPositions[idx].top}
|
return (
|
||||||
right={CategorizeAnchorPointPositions[idx].right}
|
<CategorizeHandle
|
||||||
key={idx}
|
top={CategorizeAnchorPointPositions[idx].top}
|
||||||
text={x}
|
right={CategorizeAnchorPointPositions[idx].right}
|
||||||
idx={idx}
|
key={idx}
|
||||||
></CategorizeHandle>
|
text={x}
|
||||||
))}
|
idx={idx}
|
||||||
|
></CategorizeHandle>
|
||||||
|
);
|
||||||
|
})}
|
||||||
<Flex vertical align="center" justify="center" gap={6}>
|
<Flex vertical align="center" justify="center" gap={6}>
|
||||||
<OperatorIcon
|
<OperatorIcon
|
||||||
name={data.label as Operator}
|
name={data.label as Operator}
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
} from 'reactflow';
|
} from 'reactflow';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { devtools } from 'zustand/middleware';
|
import { devtools } from 'zustand/middleware';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
import { Operator } from './constant';
|
import { Operator } from './constant';
|
||||||
import { NodeData } from './interface';
|
import { NodeData } from './interface';
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ export type RFState = {
|
|||||||
onConnect: OnConnect;
|
onConnect: OnConnect;
|
||||||
setNodes: (nodes: Node[]) => void;
|
setNodes: (nodes: Node[]) => void;
|
||||||
setEdges: (edges: Edge[]) => void;
|
setEdges: (edges: Edge[]) => void;
|
||||||
updateNodeForm: (nodeId: string, values: any) => void;
|
updateNodeForm: (nodeId: string, values: any, path?: string[]) => void;
|
||||||
onSelectionChange: OnSelectionChangeFunc;
|
onSelectionChange: OnSelectionChangeFunc;
|
||||||
addNode: (nodes: Node) => void;
|
addNode: (nodes: Node) => void;
|
||||||
getNode: (id?: string | null) => Node<NodeData> | undefined;
|
getNode: (id?: string | null) => Node<NodeData> | 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
|
// this is our useStore hook that we can use in our components to get parts of the store and call actions
|
||||||
const useGraphStore = create<RFState>()(
|
const useGraphStore = create<RFState>()(
|
||||||
devtools(
|
devtools(
|
||||||
(set, get) => ({
|
immer((set, get) => ({
|
||||||
nodes: [] as Node[],
|
nodes: [] as Node[],
|
||||||
edges: [] as Edge[],
|
edges: [] as Edge[],
|
||||||
selectedNodeIds: [] as string[],
|
selectedNodeIds: [] as string[],
|
||||||
@ -108,6 +109,8 @@ const useGraphStore = create<RFState>()(
|
|||||||
edges: addEdge(connection, get().edges),
|
edges: addEdge(connection, get().edges),
|
||||||
});
|
});
|
||||||
get().deletePreviousEdgeOfClassificationNode(connection);
|
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) => {
|
getEdge: (id: string) => {
|
||||||
return get().edges.find((x) => x.id === id);
|
return get().edges.find((x) => x.id === id);
|
||||||
@ -115,8 +118,23 @@ const useGraphStore = create<RFState>()(
|
|||||||
updateFormDataOnConnect: (connection: Connection) => {
|
updateFormDataOnConnect: (connection: Connection) => {
|
||||||
const { getOperatorTypeFromId, updateNodeForm } = get();
|
const { getOperatorTypeFromId, updateNodeForm } = get();
|
||||||
const { source, target, sourceHandle } = connection;
|
const { source, target, sourceHandle } = connection;
|
||||||
if (source && getOperatorTypeFromId(source) === Operator.Relevant) {
|
const operatorType = getOperatorTypeFromId(source);
|
||||||
updateNodeForm(source, { [sourceHandle as string]: target });
|
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) => {
|
deletePreviousEdgeOfClassificationNode: (connection: Connection) => {
|
||||||
@ -166,13 +184,30 @@ const useGraphStore = create<RFState>()(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteEdgeById: (id: string) => {
|
deleteEdgeById: (id: string) => {
|
||||||
const { edges, updateNodeForm } = get();
|
const { edges, updateNodeForm, getOperatorTypeFromId } = get();
|
||||||
const currentEdge = edges.find((x) => x.id === id);
|
const currentEdge = edges.find((x) => x.id === id);
|
||||||
|
|
||||||
if (currentEdge) {
|
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
|
// After deleting the edge, set the corresponding field in the node's form field to undefined
|
||||||
updateNodeForm(currentEdge.source, {
|
switch (operatorType) {
|
||||||
[currentEdge.sourceHandle as string]: undefined,
|
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({
|
set({
|
||||||
edges: edges.filter((edge) => edge.id !== id),
|
edges: edges.filter((edge) => edge.id !== id),
|
||||||
@ -203,7 +238,7 @@ const useGraphStore = create<RFState>()(
|
|||||||
findNodeByName: (name: Operator) => {
|
findNodeByName: (name: Operator) => {
|
||||||
return get().nodes.find((x) => x.data.label === name);
|
return get().nodes.find((x) => x.data.label === name);
|
||||||
},
|
},
|
||||||
updateNodeForm: (nodeId: string, values: any) => {
|
updateNodeForm: (nodeId: string, values: any, path: string[] = []) => {
|
||||||
set({
|
set({
|
||||||
nodes: get().nodes.map((node) => {
|
nodes: get().nodes.map((node) => {
|
||||||
if (node.id === nodeId) {
|
if (node.id === nodeId) {
|
||||||
@ -211,11 +246,17 @@ const useGraphStore = create<RFState>()(
|
|||||||
// ...node.data,
|
// ...node.data,
|
||||||
// form: { ...node.data.form, ...values },
|
// form: { ...node.data.form, ...values },
|
||||||
// };
|
// };
|
||||||
|
let nextForm: Record<string, unknown> = { ...node.data.form };
|
||||||
|
if (path.length === 0) {
|
||||||
|
nextForm = Object.assign(nextForm, values);
|
||||||
|
} else {
|
||||||
|
lodashSet(nextForm, path, values);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...node,
|
...node,
|
||||||
data: {
|
data: {
|
||||||
...node.data,
|
...node.data,
|
||||||
form: { ...node.data.form, ...values },
|
form: nextForm,
|
||||||
},
|
},
|
||||||
} as any;
|
} as any;
|
||||||
}
|
}
|
||||||
@ -247,7 +288,7 @@ const useGraphStore = create<RFState>()(
|
|||||||
setClickedNodeId: (id?: string) => {
|
setClickedNodeId: (id?: string) => {
|
||||||
set({ clickedNodeId: id });
|
set({ clickedNodeId: id });
|
||||||
},
|
},
|
||||||
}),
|
})),
|
||||||
{ name: 'graph' },
|
{ name: 'graph' },
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user