mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-14 05:26:03 +08:00
feat: set the edge as the data source to achieve two-way linkage betw… (#1299)
### What problem does this PR solve? feat: set the edge as the data source to achieve two-way linkage between the edge and the to field. #918 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
5a1e01d96f
commit
840e921e96
@ -22,7 +22,8 @@ const CategorizeHandle = ({ top, right, text, idx }: IProps) => {
|
|||||||
<Handle
|
<Handle
|
||||||
type="source"
|
type="source"
|
||||||
position={Position.Right}
|
position={Position.Right}
|
||||||
id={`CategorizeHandle${idx}`}
|
// id={`CategorizeHandle${idx}`}
|
||||||
|
id={text}
|
||||||
isConnectable
|
isConnectable
|
||||||
style={{
|
style={{
|
||||||
...DEFAULT_HANDLE_STYLE,
|
...DEFAULT_HANDLE_STYLE,
|
||||||
|
@ -11,10 +11,7 @@ const DynamicCategorize = ({ nodeId }: IProps) => {
|
|||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
const form = Form.useFormInstance();
|
const form = Form.useFormInstance();
|
||||||
const options = useBuildCategorizeToOptions();
|
const options = useBuildCategorizeToOptions();
|
||||||
const { handleSelectChange } = useHandleToSelectChange(
|
const { handleSelectChange } = useHandleToSelectChange(nodeId);
|
||||||
options.map((x) => x.value),
|
|
||||||
nodeId,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -64,7 +61,9 @@ const DynamicCategorize = ({ nodeId }: IProps) => {
|
|||||||
<Select
|
<Select
|
||||||
allowClear
|
allowClear
|
||||||
options={options}
|
options={options}
|
||||||
onChange={handleSelectChange}
|
onChange={handleSelectChange(
|
||||||
|
form.getFieldValue(['items', field.name, 'name']),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import omit from 'lodash/omit';
|
import omit from 'lodash/omit';
|
||||||
import { useCallback, useEffect, useRef } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
|
import { Edge, Node } from 'reactflow';
|
||||||
import { Operator } from '../constant';
|
import { Operator } from '../constant';
|
||||||
import {
|
import {
|
||||||
ICategorizeItem,
|
ICategorizeItem,
|
||||||
ICategorizeItemResult,
|
ICategorizeItemResult,
|
||||||
IOperatorForm,
|
IOperatorForm,
|
||||||
|
NodeData,
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
import useGraphStore from '../store';
|
import useGraphStore from '../store';
|
||||||
|
|
||||||
@ -33,10 +35,18 @@ export const useBuildCategorizeToOptions = () => {
|
|||||||
*/
|
*/
|
||||||
const buildCategorizeListFromObject = (
|
const buildCategorizeListFromObject = (
|
||||||
categorizeItem: ICategorizeItemResult,
|
categorizeItem: ICategorizeItemResult,
|
||||||
|
edges: Edge[],
|
||||||
|
node?: Node<NodeData>,
|
||||||
) => {
|
) => {
|
||||||
|
// Categorize's to field has two data sources, with edges as the data source.
|
||||||
|
// Changes in the edge or to field need to be synchronized to the form field.
|
||||||
return Object.keys(categorizeItem).reduce<Array<ICategorizeItem>>(
|
return Object.keys(categorizeItem).reduce<Array<ICategorizeItem>>(
|
||||||
(pre, cur) => {
|
(pre, cur) => {
|
||||||
pre.push({ name: cur, ...categorizeItem[cur] });
|
// synchronize edge data to the to field
|
||||||
|
const edge = edges.find(
|
||||||
|
(x) => x.source === node?.id && x.sourceHandle === cur,
|
||||||
|
);
|
||||||
|
pre.push({ name: cur, ...categorizeItem[cur], to: edge?.target });
|
||||||
return pre;
|
return pre;
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
@ -70,6 +80,8 @@ export const useHandleFormValuesChange = ({
|
|||||||
form,
|
form,
|
||||||
node,
|
node,
|
||||||
}: IOperatorForm) => {
|
}: IOperatorForm) => {
|
||||||
|
const edges = useGraphStore((state) => state.edges);
|
||||||
|
|
||||||
const handleValuesChange = useCallback(
|
const handleValuesChange = useCallback(
|
||||||
(changedValues: any, values: any) => {
|
(changedValues: any, values: any) => {
|
||||||
console.info(changedValues, values);
|
console.info(changedValues, values);
|
||||||
@ -85,43 +97,29 @@ export const useHandleFormValuesChange = ({
|
|||||||
form?.setFieldsValue({
|
form?.setFieldsValue({
|
||||||
items: buildCategorizeListFromObject(
|
items: buildCategorizeListFromObject(
|
||||||
get(node, 'data.form.category_description', {}),
|
get(node, 'data.form.category_description', {}),
|
||||||
|
edges,
|
||||||
|
node,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}, [form, node]);
|
}, [form, node, edges]);
|
||||||
|
|
||||||
return { handleValuesChange };
|
return { handleValuesChange };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useHandleToSelectChange = (
|
export const useHandleToSelectChange = (nodeId?: string) => {
|
||||||
opstionIds: string[],
|
const { addEdge } = useGraphStore((state) => state);
|
||||||
nodeId?: string,
|
|
||||||
) => {
|
|
||||||
// const [previousTarget, setPreviousTarget] = useState('');
|
|
||||||
const previousTarget = useRef('');
|
|
||||||
const { addEdge, deleteEdgeBySourceAndTarget } = useGraphStore(
|
|
||||||
(state) => state,
|
|
||||||
);
|
|
||||||
const handleSelectChange = useCallback(
|
const handleSelectChange = useCallback(
|
||||||
(value?: string) => {
|
(name?: string) => (value?: string) => {
|
||||||
if (nodeId) {
|
if (nodeId && value && name) {
|
||||||
if (previousTarget.current) {
|
|
||||||
// delete previous edge
|
|
||||||
deleteEdgeBySourceAndTarget(nodeId, previousTarget.current);
|
|
||||||
}
|
|
||||||
if (value) {
|
|
||||||
addEdge({
|
addEdge({
|
||||||
source: nodeId,
|
source: nodeId,
|
||||||
target: value,
|
target: value,
|
||||||
sourceHandle: 'b',
|
sourceHandle: name,
|
||||||
targetHandle: 'd',
|
targetHandle: null,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
// if the value is empty, delete the edges between the current node and all nodes in the drop-down box.
|
|
||||||
}
|
|
||||||
previousTarget.current = value;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[addEdge, nodeId, deleteEdgeBySourceAndTarget],
|
[addEdge, nodeId],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { handleSelectChange };
|
return { handleSelectChange };
|
||||||
|
@ -169,7 +169,7 @@ export const useWatchGraphChange = () => {
|
|||||||
const edges = useGraphStore((state) => state.edges);
|
const edges = useGraphStore((state) => state.edges);
|
||||||
useDebounceEffect(
|
useDebounceEffect(
|
||||||
() => {
|
() => {
|
||||||
console.info('useDebounceEffect');
|
// console.info('useDebounceEffect');
|
||||||
},
|
},
|
||||||
[nodes, edges],
|
[nodes, edges],
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type {} from '@redux-devtools/extension';
|
import type {} from '@redux-devtools/extension';
|
||||||
import { humanId } from 'human-id';
|
import { humanId } from 'human-id';
|
||||||
|
import lodashSet from 'lodash/set';
|
||||||
import {
|
import {
|
||||||
Connection,
|
Connection,
|
||||||
Edge,
|
Edge,
|
||||||
@ -36,6 +37,7 @@ export type RFState = {
|
|||||||
addNode: (nodes: Node) => void;
|
addNode: (nodes: Node) => void;
|
||||||
getNode: (id: string) => Node | undefined;
|
getNode: (id: string) => Node | undefined;
|
||||||
addEdge: (connection: Connection) => void;
|
addEdge: (connection: Connection) => void;
|
||||||
|
getEdge: (id: string) => Edge | undefined;
|
||||||
deletePreviousEdgeOfClassificationNode: (connection: Connection) => void;
|
deletePreviousEdgeOfClassificationNode: (connection: Connection) => void;
|
||||||
duplicateNode: (id: string) => void;
|
duplicateNode: (id: string) => void;
|
||||||
deleteEdge: () => void;
|
deleteEdge: () => void;
|
||||||
@ -43,7 +45,7 @@ export type RFState = {
|
|||||||
deleteNodeById: (id: string) => void;
|
deleteNodeById: (id: string) => void;
|
||||||
deleteEdgeBySourceAndTarget: (source: string, target: string) => void;
|
deleteEdgeBySourceAndTarget: (source: string, target: string) => void;
|
||||||
findNodeByName: (operatorName: Operator) => Node | undefined;
|
findNodeByName: (operatorName: Operator) => Node | undefined;
|
||||||
findNodeById: (id: string) => Node | undefined;
|
updateMutableNodeFormItem: (id: string, field: string, value: any) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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
|
||||||
@ -92,6 +94,10 @@ const useGraphStore = create<RFState>()(
|
|||||||
set({
|
set({
|
||||||
edges: addEdge(connection, get().edges),
|
edges: addEdge(connection, get().edges),
|
||||||
});
|
});
|
||||||
|
get().deletePreviousEdgeOfClassificationNode(connection);
|
||||||
|
},
|
||||||
|
getEdge: (id: string) => {
|
||||||
|
return get().edges.find((x) => x.id === id);
|
||||||
},
|
},
|
||||||
deletePreviousEdgeOfClassificationNode: (connection: Connection) => {
|
deletePreviousEdgeOfClassificationNode: (connection: Connection) => {
|
||||||
// Delete the edge on the classification node anchor when the anchor is connected to other nodes
|
// Delete the edge on the classification node anchor when the anchor is connected to other nodes
|
||||||
@ -164,9 +170,6 @@ 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);
|
||||||
},
|
},
|
||||||
findNodeById: (id: string) => {
|
|
||||||
return get().nodes.find((x) => x.id === id);
|
|
||||||
},
|
|
||||||
updateNodeForm: (nodeId: string, values: any) => {
|
updateNodeForm: (nodeId: string, values: any) => {
|
||||||
set({
|
set({
|
||||||
nodes: get().nodes.map((node) => {
|
nodes: get().nodes.map((node) => {
|
||||||
@ -178,6 +181,13 @@ const useGraphStore = create<RFState>()(
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
updateMutableNodeFormItem: (id: string, field: string, value: any) => {
|
||||||
|
const { nodes } = get();
|
||||||
|
const idx = nodes.findIndex((x) => x.id === id);
|
||||||
|
if (idx) {
|
||||||
|
lodashSet(nodes, [idx, 'data', 'form', field], value);
|
||||||
|
}
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
{ name: 'graph' },
|
{ name: 'graph' },
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user