mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-26 08:56:47 +08:00
### What problem does this PR solve? Feat: Add note node #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -269,9 +269,13 @@ function useResizeIterationNode() {
|
||||
|
||||
return { resizeIterationNode };
|
||||
}
|
||||
type CanvasMouseEvent = Pick<
|
||||
React.MouseEvent<HTMLElement>,
|
||||
'clientX' | 'clientY'
|
||||
>;
|
||||
|
||||
export function useAddNode(reactFlowInstance?: ReactFlowInstance<any, any>) {
|
||||
const { edges, nodes, addEdge, addNode, getNode, updateNode } = useGraphStore(
|
||||
const { edges, nodes, addEdge, addNode, getNode } = useGraphStore(
|
||||
(state) => state,
|
||||
);
|
||||
const getNodeName = useGetNodeName();
|
||||
@ -290,7 +294,7 @@ export function useAddNode(reactFlowInstance?: ReactFlowInstance<any, any>) {
|
||||
position: Position.Right,
|
||||
},
|
||||
) =>
|
||||
(event?: React.MouseEvent<HTMLElement>) => {
|
||||
(event?: CanvasMouseEvent) => {
|
||||
const nodeId = params.nodeId;
|
||||
|
||||
const node = getNode(nodeId);
|
||||
@ -303,7 +307,7 @@ export function useAddNode(reactFlowInstance?: ReactFlowInstance<any, any>) {
|
||||
y: event?.clientY || 0,
|
||||
});
|
||||
|
||||
if (params.position === Position.Right) {
|
||||
if (params.position === Position.Right && type !== Operator.Note) {
|
||||
position = calculateNewlyBackChildPosition(nodeId, params.id);
|
||||
}
|
||||
|
||||
@ -420,9 +424,16 @@ export function useAddNode(reactFlowInstance?: ReactFlowInstance<any, any>) {
|
||||
initializeOperatorParams,
|
||||
nodes,
|
||||
reactFlowInstance,
|
||||
updateNode,
|
||||
resizeIterationNode,
|
||||
],
|
||||
);
|
||||
|
||||
return { addCanvasNode };
|
||||
const addNoteNode = useCallback(
|
||||
(e: CanvasMouseEvent) => {
|
||||
addCanvasNode(Operator.Note)(e);
|
||||
},
|
||||
[addCanvasNode],
|
||||
);
|
||||
|
||||
return { addCanvasNode, addNoteNode };
|
||||
}
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
import { IEventList, MessageEventType } from '@/hooks/use-send-message';
|
||||
import {
|
||||
IEventList,
|
||||
INodeEvent,
|
||||
MessageEventType,
|
||||
} from '@/hooks/use-send-message';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
export const ExcludeTypes = [
|
||||
@ -41,11 +45,13 @@ export function useCacheChatLog() {
|
||||
}, []);
|
||||
|
||||
const currentEventListWithoutMessage = useMemo(() => {
|
||||
return eventList.filter(
|
||||
const list = eventList.filter(
|
||||
(x) =>
|
||||
x.message_id === currentMessageId &&
|
||||
ExcludeTypes.every((y) => y !== x.event),
|
||||
);
|
||||
|
||||
return list as INodeEvent[];
|
||||
}, [currentMessageId, eventList]);
|
||||
|
||||
return {
|
||||
|
||||
35
web/src/pages/agent/hooks/use-move-note.ts
Normal file
35
web/src/pages/agent/hooks/use-move-note.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { useMouse } from 'ahooks';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
export function useMoveNote() {
|
||||
const ref = useRef<SVGSVGElement>(null);
|
||||
const mouse = useMouse();
|
||||
const [imgVisible, setImgVisible] = useState(false);
|
||||
|
||||
const toggleVisible = useCallback((visible: boolean) => {
|
||||
setImgVisible(visible);
|
||||
}, []);
|
||||
|
||||
const showImage = useCallback(() => {
|
||||
toggleVisible(true);
|
||||
}, [toggleVisible]);
|
||||
|
||||
const hideImage = useCallback(() => {
|
||||
toggleVisible(false);
|
||||
}, [toggleVisible]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current) {
|
||||
ref.current.style.top = `${mouse.clientY - 70}px`;
|
||||
ref.current.style.left = `${mouse.clientX + 10}px`;
|
||||
}
|
||||
}, [mouse.clientX, mouse.clientY]);
|
||||
|
||||
return {
|
||||
ref,
|
||||
showImage,
|
||||
hideImage,
|
||||
mouse,
|
||||
imgVisible,
|
||||
};
|
||||
}
|
||||
@ -1,154 +1,6 @@
|
||||
import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent';
|
||||
import { settledModelVariableMap } from '@/constants/knowledge';
|
||||
import { omit } from 'lodash';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { UseFormReturn, useWatch } from 'react-hook-form';
|
||||
import { Operator } from '../constant';
|
||||
import useGraphStore from '../store';
|
||||
import { buildCategorizeObjectFromList, convertToStringArray } from '../utils';
|
||||
|
||||
export const useHandleFormValuesChange = (
|
||||
operatorName: Operator,
|
||||
id?: string,
|
||||
form?: UseFormReturn,
|
||||
) => {
|
||||
const updateNodeForm = useGraphStore((state) => state.updateNodeForm);
|
||||
|
||||
const handleValuesChange = useCallback(
|
||||
(changedValues: any, values: any) => {
|
||||
let nextValues: any = values;
|
||||
// Fixed the issue that the related form value does not change after selecting the freedom field of the model
|
||||
if (
|
||||
Object.keys(changedValues).length === 1 &&
|
||||
'parameter' in changedValues &&
|
||||
changedValues['parameter'] in settledModelVariableMap
|
||||
) {
|
||||
nextValues = {
|
||||
...values,
|
||||
...settledModelVariableMap[
|
||||
changedValues['parameter'] as keyof typeof settledModelVariableMap
|
||||
],
|
||||
};
|
||||
}
|
||||
if (id) {
|
||||
updateNodeForm(id, nextValues);
|
||||
}
|
||||
},
|
||||
[updateNodeForm, id],
|
||||
);
|
||||
|
||||
let values = useWatch({ control: form?.control });
|
||||
|
||||
// console.log('🚀 ~ x:', values);
|
||||
|
||||
useEffect(() => {
|
||||
// Manually triggered form updates are synchronized to the canvas
|
||||
if (id && form?.formState.isDirty) {
|
||||
values = form?.getValues();
|
||||
let nextValues: any = values;
|
||||
// run(id, nextValues);
|
||||
|
||||
const categoryDescriptionRegex = /items\.\d+\.name/g;
|
||||
|
||||
if (operatorName === Operator.Categorize) {
|
||||
console.log('🚀 ~ useEffect ~ values:', values);
|
||||
const categoryDescription = Array.isArray(values.items)
|
||||
? buildCategorizeObjectFromList(values.items)
|
||||
: {};
|
||||
if (categoryDescription) {
|
||||
nextValues = {
|
||||
...omit(values, 'items'),
|
||||
category_description: categoryDescription,
|
||||
};
|
||||
}
|
||||
} else if (operatorName === Operator.Message) {
|
||||
nextValues = {
|
||||
...values,
|
||||
content: convertToStringArray(values.content),
|
||||
};
|
||||
}
|
||||
|
||||
updateNodeForm(id, nextValues);
|
||||
}
|
||||
}, [form?.formState.isDirty, id, operatorName, updateNodeForm, values]);
|
||||
|
||||
// useEffect(() => {
|
||||
// form?.subscribe({
|
||||
// formState: { values: true },
|
||||
// callback: ({ values }) => {
|
||||
// // console.info('subscribe', values);
|
||||
// },
|
||||
// });
|
||||
// }, [form]);
|
||||
|
||||
return { handleValuesChange };
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = form?.watch((value, { name, type, values }) => {
|
||||
if (id && name) {
|
||||
let nextValues: any = value;
|
||||
|
||||
// Fixed the issue that the related form value does not change after selecting the freedom field of the model
|
||||
if (
|
||||
name === 'parameter' &&
|
||||
value['parameter'] in settledModelVariableMap
|
||||
) {
|
||||
nextValues = {
|
||||
...value,
|
||||
...settledModelVariableMap[
|
||||
value['parameter'] as keyof typeof settledModelVariableMap
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const categoryDescriptionRegex = /items\.\d+\.name/g;
|
||||
if (
|
||||
operatorName === Operator.Categorize &&
|
||||
categoryDescriptionRegex.test(name)
|
||||
) {
|
||||
nextValues = {
|
||||
...omit(value, 'items'),
|
||||
category_description: buildCategorizeObjectFromList(value.items),
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
operatorName === Operator.Code &&
|
||||
type === 'change' &&
|
||||
name === 'lang'
|
||||
) {
|
||||
nextValues = {
|
||||
...value,
|
||||
script: CodeTemplateStrMap[value.lang as ProgrammingLanguage],
|
||||
};
|
||||
}
|
||||
|
||||
if (operatorName === Operator.Message) {
|
||||
nextValues = {
|
||||
...value,
|
||||
content: convertToStringArray(value.content),
|
||||
};
|
||||
}
|
||||
|
||||
// Manually triggered form updates are synchronized to the canvas
|
||||
if (form.formState.isDirty) {
|
||||
console.log(
|
||||
'🚀 ~ useEffect ~ value:',
|
||||
name,
|
||||
type,
|
||||
values,
|
||||
operatorName,
|
||||
);
|
||||
// run(id, nextValues);
|
||||
updateNodeForm(id, nextValues);
|
||||
}
|
||||
}
|
||||
});
|
||||
return () => subscription?.unsubscribe();
|
||||
}, [form, form?.watch, id, operatorName, updateNodeForm]);
|
||||
|
||||
return { handleValuesChange };
|
||||
};
|
||||
|
||||
export function useWatchFormChange(id?: string, form?: UseFormReturn) {
|
||||
let values = useWatch({ control: form?.control });
|
||||
|
||||
Reference in New Issue
Block a user