mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 12:32:30 +08:00
Feat: Fixed an issue where dragged operators within an iteration were not associated with the iteration. #10866 (#10969)
### What problem does this PR solve? Feat: Fixed an issue where dragged operators within an iteration were not associated with the iteration. #10866 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1724,6 +1724,7 @@ Important structured information may include: names, dates, locations, events, k
|
|||||||
},
|
},
|
||||||
structuredOutput: {
|
structuredOutput: {
|
||||||
configuration: 'Configuration',
|
configuration: 'Configuration',
|
||||||
|
structuredOutput: 'Structured output',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
llmTools: {
|
llmTools: {
|
||||||
|
|||||||
@ -1605,6 +1605,7 @@ Tokenizer 会根据所选方式将内容存储为对应的数据结构。`,
|
|||||||
switchPromptMessage: '提示词将发生变化,请确认是否放弃已有提示词?',
|
switchPromptMessage: '提示词将发生变化,请确认是否放弃已有提示词?',
|
||||||
structuredOutput: {
|
structuredOutput: {
|
||||||
configuration: '配置',
|
configuration: '配置',
|
||||||
|
structuredOutput: '结构化输出',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import {
|
|||||||
NodeTypes,
|
NodeTypes,
|
||||||
Position,
|
Position,
|
||||||
ReactFlow,
|
ReactFlow,
|
||||||
|
ReactFlowInstance,
|
||||||
} from '@xyflow/react';
|
} from '@xyflow/react';
|
||||||
import '@xyflow/react/dist/style.css';
|
import '@xyflow/react/dist/style.css';
|
||||||
import { NotebookPen } from 'lucide-react';
|
import { NotebookPen } from 'lucide-react';
|
||||||
@ -27,11 +28,7 @@ import {
|
|||||||
} from '../context';
|
} from '../context';
|
||||||
|
|
||||||
import FormSheet from '../form-sheet/next';
|
import FormSheet from '../form-sheet/next';
|
||||||
import {
|
import { useSelectCanvasData, useValidateConnection } from '../hooks';
|
||||||
useHandleDrop,
|
|
||||||
useSelectCanvasData,
|
|
||||||
useValidateConnection,
|
|
||||||
} from '../hooks';
|
|
||||||
import { useAddNode } from '../hooks/use-add-node';
|
import { useAddNode } from '../hooks/use-add-node';
|
||||||
import { useBeforeDelete } from '../hooks/use-before-delete';
|
import { useBeforeDelete } from '../hooks/use-before-delete';
|
||||||
import { useCacheChatLog } from '../hooks/use-cache-chat-log';
|
import { useCacheChatLog } from '../hooks/use-cache-chat-log';
|
||||||
@ -124,8 +121,8 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
|||||||
} = useSelectCanvasData();
|
} = useSelectCanvasData();
|
||||||
const isValidConnection = useValidateConnection();
|
const isValidConnection = useValidateConnection();
|
||||||
|
|
||||||
const { onDrop, onDragOver, setReactFlowInstance, reactFlowInstance } =
|
const [reactFlowInstance, setReactFlowInstance] =
|
||||||
useHandleDrop();
|
useState<ReactFlowInstance<any, any>>();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
onNodeClick,
|
onNodeClick,
|
||||||
@ -204,7 +201,6 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
|||||||
onMove,
|
onMove,
|
||||||
nodeId,
|
nodeId,
|
||||||
} = useConnectionDrag(
|
} = useConnectionDrag(
|
||||||
reactFlowInstance,
|
|
||||||
originalOnConnect,
|
originalOnConnect,
|
||||||
showModal,
|
showModal,
|
||||||
hideModal,
|
hideModal,
|
||||||
@ -214,6 +210,7 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
|||||||
removePlaceholderNode,
|
removePlaceholderNode,
|
||||||
clearActiveDropdown,
|
clearActiveDropdown,
|
||||||
checkAndRemoveExistingPlaceholder,
|
checkAndRemoveExistingPlaceholder,
|
||||||
|
reactFlowInstance,
|
||||||
);
|
);
|
||||||
|
|
||||||
const onPaneClick = useCallback(() => {
|
const onPaneClick = useCallback(() => {
|
||||||
@ -286,11 +283,9 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
|||||||
onConnect={handleConnect}
|
onConnect={handleConnect}
|
||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
edgeTypes={edgeTypes}
|
edgeTypes={edgeTypes}
|
||||||
onDrop={onDrop}
|
|
||||||
onConnectStart={onConnectStart}
|
onConnectStart={onConnectStart}
|
||||||
onConnectEnd={onConnectEnd}
|
onConnectEnd={onConnectEnd}
|
||||||
onMove={onMove}
|
onMove={onMove}
|
||||||
onDragOver={onDragOver}
|
|
||||||
onNodeClick={onNodeClick}
|
onNodeClick={onNodeClick}
|
||||||
onPaneClick={onPaneClick}
|
onPaneClick={onPaneClick}
|
||||||
onInit={setReactFlowInstance}
|
onInit={setReactFlowInstance}
|
||||||
|
|||||||
@ -803,6 +803,7 @@ export const RestrictedUpstreamMap = {
|
|||||||
[Operator.HierarchicalMerger]: [Operator.Begin],
|
[Operator.HierarchicalMerger]: [Operator.Begin],
|
||||||
[Operator.Tokenizer]: [Operator.Begin],
|
[Operator.Tokenizer]: [Operator.Begin],
|
||||||
[Operator.Extractor]: [Operator.Begin],
|
[Operator.Extractor]: [Operator.Begin],
|
||||||
|
[Operator.File]: [Operator.Begin],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NodeMap = {
|
export const NodeMap = {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { cn } from '@/lib/utils';
|
|||||||
import { get, isEmpty, isPlainObject } from 'lodash';
|
import { get, isEmpty, isPlainObject } from 'lodash';
|
||||||
import { ChevronRight } from 'lucide-react';
|
import { ChevronRight } from 'lucide-react';
|
||||||
import { PropsWithChildren, ReactNode, useCallback } from 'react';
|
import { PropsWithChildren, ReactNode, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { JsonSchemaDataType, VariableType } from '../../constant';
|
import { JsonSchemaDataType, VariableType } from '../../constant';
|
||||||
import { useGetStructuredOutputByValue } from '../../hooks/use-build-structured-output';
|
import { useGetStructuredOutputByValue } from '../../hooks/use-build-structured-output';
|
||||||
import {
|
import {
|
||||||
@ -27,6 +28,7 @@ export function StructuredOutputSecondaryMenu({
|
|||||||
click,
|
click,
|
||||||
type,
|
type,
|
||||||
}: StructuredOutputSecondaryMenuProps) {
|
}: StructuredOutputSecondaryMenuProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const filterStructuredOutput = useGetStructuredOutputByValue();
|
const filterStructuredOutput = useGetStructuredOutputByValue();
|
||||||
const structuredOutput = filterStructuredOutput(data.value);
|
const structuredOutput = filterStructuredOutput(data.value);
|
||||||
|
|
||||||
@ -113,7 +115,9 @@ export function StructuredOutputSecondaryMenu({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<section className="p-2">
|
<section className="p-2">
|
||||||
<div className="p-1">{data?.parentLabel} structured output:</div>
|
<div className="p-1">
|
||||||
|
{t('flow.structuredOutput.structuredOutput')}
|
||||||
|
</div>
|
||||||
{renderAgentStructuredOutput(structuredOutput, data)}
|
{renderAgentStructuredOutput(structuredOutput, data)}
|
||||||
</section>
|
</section>
|
||||||
</HoverCardContent>
|
</HoverCardContent>
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@/components/ui/form';
|
} from '@/components/ui/form';
|
||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/components/ui/switch';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
|
||||||
import { FormTooltip } from '@/components/ui/tooltip';
|
import { FormTooltip } from '@/components/ui/tooltip';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { Plus } from 'lucide-react';
|
import { Plus } from 'lucide-react';
|
||||||
@ -22,6 +21,7 @@ import { ParameterDialog } from '../begin-form/parameter-dialog';
|
|||||||
import { QueryTable } from '../begin-form/query-table';
|
import { QueryTable } from '../begin-form/query-table';
|
||||||
import { useEditQueryRecord } from '../begin-form/use-edit-query';
|
import { useEditQueryRecord } from '../begin-form/use-edit-query';
|
||||||
import { Output } from '../components/output';
|
import { Output } from '../components/output';
|
||||||
|
import { PromptEditor } from '../components/prompt-editor';
|
||||||
import { useValues } from './use-values';
|
import { useValues } from './use-values';
|
||||||
import { useWatchFormChange } from './use-watch-change';
|
import { useWatchFormChange } from './use-watch-change';
|
||||||
|
|
||||||
@ -108,11 +108,7 @@ function UserFillUpForm({ node }: INextOperatorForm) {
|
|||||||
{t('flow.msg')}
|
{t('flow.msg')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Textarea
|
<PromptEditor value={field.value} onChange={field.onChange} />
|
||||||
rows={5}
|
|
||||||
{...field}
|
|
||||||
placeholder={t('common.pleaseInput')}
|
|
||||||
></Textarea>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@ -1,72 +1,14 @@
|
|||||||
import {
|
import { Connection, Edge, getOutgoers } from '@xyflow/react';
|
||||||
Connection,
|
import React, { useCallback, useEffect } from 'react';
|
||||||
Edge,
|
|
||||||
getOutgoers,
|
|
||||||
Node,
|
|
||||||
Position,
|
|
||||||
ReactFlowInstance,
|
|
||||||
} from '@xyflow/react';
|
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
||||||
// import { shallow } from 'zustand/shallow';
|
// import { shallow } from 'zustand/shallow';
|
||||||
import { settledModelVariableMap } from '@/constants/knowledge';
|
import { settledModelVariableMap } from '@/constants/knowledge';
|
||||||
import { useFetchModelId } from '@/hooks/logic-hooks';
|
|
||||||
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||||
import { humanId } from 'human-id';
|
|
||||||
import { get, lowerFirst, omit } from 'lodash';
|
import { get, lowerFirst, omit } from 'lodash';
|
||||||
import { UseFormReturn } from 'react-hook-form';
|
import { UseFormReturn } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import { Operator, RestrictedUpstreamMap } from './constant';
|
||||||
initialAgentValues,
|
|
||||||
initialAkShareValues,
|
|
||||||
initialArXivValues,
|
|
||||||
initialBaiduFanyiValues,
|
|
||||||
initialBaiduValues,
|
|
||||||
initialBeginValues,
|
|
||||||
initialBingValues,
|
|
||||||
initialCategorizeValues,
|
|
||||||
initialCodeValues,
|
|
||||||
initialCrawlerValues,
|
|
||||||
initialDeepLValues,
|
|
||||||
initialDuckValues,
|
|
||||||
initialEmailValues,
|
|
||||||
initialExeSqlValues,
|
|
||||||
initialGithubValues,
|
|
||||||
initialGoogleScholarValues,
|
|
||||||
initialGoogleValues,
|
|
||||||
initialInvokeValues,
|
|
||||||
initialIterationValues,
|
|
||||||
initialJin10Values,
|
|
||||||
initialKeywordExtractValues,
|
|
||||||
initialMessageValues,
|
|
||||||
initialNoteValues,
|
|
||||||
initialPubMedValues,
|
|
||||||
initialQWeatherValues,
|
|
||||||
initialRelevantValues,
|
|
||||||
initialRetrievalValues,
|
|
||||||
initialRewriteQuestionValues,
|
|
||||||
initialSearXNGValues,
|
|
||||||
initialStringTransformValues,
|
|
||||||
initialSwitchValues,
|
|
||||||
initialTavilyExtractValues,
|
|
||||||
initialTavilyValues,
|
|
||||||
initialTuShareValues,
|
|
||||||
initialUserFillUpValues,
|
|
||||||
initialWaitingDialogueValues,
|
|
||||||
initialWenCaiValues,
|
|
||||||
initialWikipediaValues,
|
|
||||||
initialYahooFinanceValues,
|
|
||||||
NodeMap,
|
|
||||||
Operator,
|
|
||||||
RestrictedUpstreamMap,
|
|
||||||
} from './constant';
|
|
||||||
import useGraphStore, { RFState } from './store';
|
import useGraphStore, { RFState } from './store';
|
||||||
import {
|
import { buildCategorizeObjectFromList, replaceIdWithText } from './utils';
|
||||||
buildCategorizeObjectFromList,
|
|
||||||
generateNodeNamesWithIncreasingIndex,
|
|
||||||
getNodeDragHandle,
|
|
||||||
getRelativePositionToIterationNode,
|
|
||||||
replaceIdWithText,
|
|
||||||
} from './utils';
|
|
||||||
|
|
||||||
const selector = (state: RFState) => ({
|
const selector = (state: RFState) => ({
|
||||||
nodes: state.nodes,
|
nodes: state.nodes,
|
||||||
@ -86,72 +28,6 @@ export const useSelectCanvasData = () => {
|
|||||||
return useGraphStore(selector);
|
return useGraphStore(selector);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useInitializeOperatorParams = () => {
|
|
||||||
const llmId = useFetchModelId();
|
|
||||||
|
|
||||||
const initialFormValuesMap = useMemo(() => {
|
|
||||||
return {
|
|
||||||
[Operator.Begin]: initialBeginValues,
|
|
||||||
[Operator.Retrieval]: initialRetrievalValues,
|
|
||||||
[Operator.Categorize]: { ...initialCategorizeValues, llm_id: llmId },
|
|
||||||
[Operator.Relevant]: { ...initialRelevantValues, llm_id: llmId },
|
|
||||||
[Operator.RewriteQuestion]: {
|
|
||||||
...initialRewriteQuestionValues,
|
|
||||||
llm_id: llmId,
|
|
||||||
},
|
|
||||||
[Operator.Message]: initialMessageValues,
|
|
||||||
[Operator.KeywordExtract]: {
|
|
||||||
...initialKeywordExtractValues,
|
|
||||||
llm_id: llmId,
|
|
||||||
},
|
|
||||||
[Operator.DuckDuckGo]: initialDuckValues,
|
|
||||||
[Operator.Baidu]: initialBaiduValues,
|
|
||||||
[Operator.Wikipedia]: initialWikipediaValues,
|
|
||||||
[Operator.PubMed]: initialPubMedValues,
|
|
||||||
[Operator.ArXiv]: initialArXivValues,
|
|
||||||
[Operator.Google]: initialGoogleValues,
|
|
||||||
[Operator.Bing]: initialBingValues,
|
|
||||||
[Operator.GoogleScholar]: initialGoogleScholarValues,
|
|
||||||
[Operator.DeepL]: initialDeepLValues,
|
|
||||||
[Operator.SearXNG]: initialSearXNGValues,
|
|
||||||
[Operator.GitHub]: initialGithubValues,
|
|
||||||
[Operator.BaiduFanyi]: initialBaiduFanyiValues,
|
|
||||||
[Operator.QWeather]: initialQWeatherValues,
|
|
||||||
[Operator.ExeSQL]: { ...initialExeSqlValues, llm_id: llmId },
|
|
||||||
[Operator.Switch]: initialSwitchValues,
|
|
||||||
[Operator.WenCai]: initialWenCaiValues,
|
|
||||||
[Operator.AkShare]: initialAkShareValues,
|
|
||||||
[Operator.YahooFinance]: initialYahooFinanceValues,
|
|
||||||
[Operator.Jin10]: initialJin10Values,
|
|
||||||
[Operator.TuShare]: initialTuShareValues,
|
|
||||||
[Operator.Note]: initialNoteValues,
|
|
||||||
[Operator.Crawler]: initialCrawlerValues,
|
|
||||||
[Operator.Invoke]: initialInvokeValues,
|
|
||||||
[Operator.Email]: initialEmailValues,
|
|
||||||
[Operator.Iteration]: initialIterationValues,
|
|
||||||
[Operator.IterationStart]: initialIterationValues,
|
|
||||||
[Operator.Code]: initialCodeValues,
|
|
||||||
[Operator.WaitingDialogue]: initialWaitingDialogueValues,
|
|
||||||
[Operator.Agent]: { ...initialAgentValues, llm_id: llmId },
|
|
||||||
[Operator.TavilySearch]: initialTavilyValues,
|
|
||||||
[Operator.TavilyExtract]: initialTavilyExtractValues,
|
|
||||||
[Operator.Tool]: {},
|
|
||||||
[Operator.UserFillUp]: initialUserFillUpValues,
|
|
||||||
[Operator.StringTransform]: initialStringTransformValues,
|
|
||||||
[Operator.Placeholder]: {},
|
|
||||||
};
|
|
||||||
}, [llmId]);
|
|
||||||
|
|
||||||
const initializeOperatorParams = useCallback(
|
|
||||||
(operatorName: Operator) => {
|
|
||||||
return initialFormValuesMap[operatorName];
|
|
||||||
},
|
|
||||||
[initialFormValuesMap],
|
|
||||||
);
|
|
||||||
|
|
||||||
return initializeOperatorParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useHandleDrag = () => {
|
export const useHandleDrag = () => {
|
||||||
const handleDragStart = useCallback(
|
const handleDragStart = useCallback(
|
||||||
(operatorId: string) => (ev: React.DragEvent<HTMLDivElement>) => {
|
(operatorId: string) => (ev: React.DragEvent<HTMLDivElement>) => {
|
||||||
@ -173,91 +49,6 @@ export const useGetNodeName = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useHandleDrop = () => {
|
|
||||||
const addNode = useGraphStore((state) => state.addNode);
|
|
||||||
const nodes = useGraphStore((state) => state.nodes);
|
|
||||||
const [reactFlowInstance, setReactFlowInstance] =
|
|
||||||
useState<ReactFlowInstance<any, any>>();
|
|
||||||
const initializeOperatorParams = useInitializeOperatorParams();
|
|
||||||
const getNodeName = useGetNodeName();
|
|
||||||
|
|
||||||
const onDragOver = useCallback((event: React.DragEvent<HTMLDivElement>) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.dataTransfer.dropEffect = 'move';
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onDrop = useCallback(
|
|
||||||
(event: React.DragEvent<HTMLDivElement>) => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
const type = event.dataTransfer.getData('application/@xyflow/react');
|
|
||||||
|
|
||||||
// check if the dropped element is valid
|
|
||||||
if (typeof type === 'undefined' || !type) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reactFlowInstance.project was renamed to reactFlowInstance.screenToFlowPosition
|
|
||||||
// and you don't need to subtract the reactFlowBounds.left/top anymore
|
|
||||||
// details: https://@xyflow/react.dev/whats-new/2023-11-10
|
|
||||||
const position = reactFlowInstance?.screenToFlowPosition({
|
|
||||||
x: event.clientX,
|
|
||||||
y: event.clientY,
|
|
||||||
});
|
|
||||||
const newNode: Node<any> = {
|
|
||||||
id: `${type}:${humanId()}`,
|
|
||||||
type: NodeMap[type as Operator] || 'ragNode',
|
|
||||||
position: position || {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
label: `${type}`,
|
|
||||||
name: generateNodeNamesWithIncreasingIndex(getNodeName(type), nodes),
|
|
||||||
form: initializeOperatorParams(type as Operator),
|
|
||||||
},
|
|
||||||
sourcePosition: Position.Right,
|
|
||||||
targetPosition: Position.Left,
|
|
||||||
dragHandle: getNodeDragHandle(type),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (type === Operator.Iteration) {
|
|
||||||
newNode.width = 500;
|
|
||||||
newNode.height = 250;
|
|
||||||
const iterationStartNode: Node<any> = {
|
|
||||||
id: `${Operator.IterationStart}:${humanId()}`,
|
|
||||||
type: 'iterationStartNode',
|
|
||||||
position: { x: 50, y: 100 },
|
|
||||||
// draggable: false,
|
|
||||||
data: {
|
|
||||||
label: Operator.IterationStart,
|
|
||||||
name: Operator.IterationStart,
|
|
||||||
form: {},
|
|
||||||
},
|
|
||||||
parentId: newNode.id,
|
|
||||||
extent: 'parent',
|
|
||||||
};
|
|
||||||
addNode(newNode);
|
|
||||||
addNode(iterationStartNode);
|
|
||||||
} else {
|
|
||||||
const subNodeOfIteration = getRelativePositionToIterationNode(
|
|
||||||
nodes,
|
|
||||||
position,
|
|
||||||
);
|
|
||||||
if (subNodeOfIteration) {
|
|
||||||
newNode.parentId = subNodeOfIteration.parentId;
|
|
||||||
newNode.position = subNodeOfIteration.position;
|
|
||||||
newNode.extent = 'parent';
|
|
||||||
}
|
|
||||||
addNode(newNode);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[reactFlowInstance, getNodeName, nodes, initializeOperatorParams, addNode],
|
|
||||||
);
|
|
||||||
|
|
||||||
return { onDrop, onDragOver, setReactFlowInstance, reactFlowInstance };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useHandleFormValuesChange = (
|
export const useHandleFormValuesChange = (
|
||||||
operatorName: Operator,
|
operatorName: Operator,
|
||||||
id?: string,
|
id?: string,
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
import { Connection, OnConnectEnd, Position } from '@xyflow/react';
|
import {
|
||||||
|
Connection,
|
||||||
|
OnConnectEnd,
|
||||||
|
OnConnectStart,
|
||||||
|
Position,
|
||||||
|
ReactFlowInstance,
|
||||||
|
} from '@xyflow/react';
|
||||||
import { useCallback, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
import { useDropdownManager } from '../canvas/context';
|
import { useDropdownManager } from '../canvas/context';
|
||||||
import { Operator, PREVENT_CLOSE_DELAY } from '../constant';
|
import { Operator, PREVENT_CLOSE_DELAY } from '../constant';
|
||||||
@ -14,7 +20,6 @@ interface ConnectionStartParams {
|
|||||||
* Responsible for handling connection drag start and end logic
|
* Responsible for handling connection drag start and end logic
|
||||||
*/
|
*/
|
||||||
export const useConnectionDrag = (
|
export const useConnectionDrag = (
|
||||||
reactFlowInstance: any,
|
|
||||||
onConnect: (connection: Connection) => void,
|
onConnect: (connection: Connection) => void,
|
||||||
showModal: () => void,
|
showModal: () => void,
|
||||||
hideModal: () => void,
|
hideModal: () => void,
|
||||||
@ -27,6 +32,7 @@ export const useConnectionDrag = (
|
|||||||
removePlaceholderNode: () => void,
|
removePlaceholderNode: () => void,
|
||||||
clearActiveDropdown: () => void,
|
clearActiveDropdown: () => void,
|
||||||
checkAndRemoveExistingPlaceholder: () => void,
|
checkAndRemoveExistingPlaceholder: () => void,
|
||||||
|
reactFlowInstance?: ReactFlowInstance<any, any>,
|
||||||
) => {
|
) => {
|
||||||
// Reference for whether connection is established
|
// Reference for whether connection is established
|
||||||
const isConnectedRef = useRef(false);
|
const isConnectedRef = useRef(false);
|
||||||
@ -43,7 +49,7 @@ export const useConnectionDrag = (
|
|||||||
/**
|
/**
|
||||||
* Connection start handler function
|
* Connection start handler function
|
||||||
*/
|
*/
|
||||||
const onConnectStart = useCallback((event: any, params: any) => {
|
const onConnectStart: OnConnectStart = useCallback((event, params) => {
|
||||||
isConnectedRef.current = false;
|
isConnectedRef.current = false;
|
||||||
|
|
||||||
// Record mouse start position to detect click vs drag
|
// Record mouse start position to detect click vs drag
|
||||||
@ -141,16 +147,16 @@ export const useConnectionDrag = (
|
|||||||
},
|
},
|
||||||
[
|
[
|
||||||
setDropdownPosition,
|
setDropdownPosition,
|
||||||
addCanvasNode,
|
|
||||||
setCreatedPlaceholderRef,
|
|
||||||
reactFlowInstance,
|
|
||||||
calculateDropdownPosition,
|
|
||||||
setActiveDropdown,
|
|
||||||
showModal,
|
|
||||||
checkAndRemoveExistingPlaceholder,
|
checkAndRemoveExistingPlaceholder,
|
||||||
|
addCanvasNode,
|
||||||
|
reactFlowInstance,
|
||||||
removePlaceholderNode,
|
removePlaceholderNode,
|
||||||
hideModal,
|
hideModal,
|
||||||
clearActiveDropdown,
|
clearActiveDropdown,
|
||||||
|
setCreatedPlaceholderRef,
|
||||||
|
calculateDropdownPosition,
|
||||||
|
setActiveDropdown,
|
||||||
|
showModal,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { ReactFlowInstance } from '@xyflow/react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import {
|
import {
|
||||||
DROPDOWN_HORIZONTAL_OFFSET,
|
DROPDOWN_HORIZONTAL_OFFSET,
|
||||||
@ -9,7 +10,9 @@ import {
|
|||||||
* Dropdown position calculation Hook
|
* Dropdown position calculation Hook
|
||||||
* Responsible for calculating dropdown menu position relative to placeholder node
|
* Responsible for calculating dropdown menu position relative to placeholder node
|
||||||
*/
|
*/
|
||||||
export const useDropdownPosition = (reactFlowInstance: any) => {
|
export const useDropdownPosition = (
|
||||||
|
reactFlowInstance?: ReactFlowInstance<any, any>,
|
||||||
|
) => {
|
||||||
/**
|
/**
|
||||||
* Calculate dropdown menu position
|
* Calculate dropdown menu position
|
||||||
* @param clientX Mouse click screen X coordinate
|
* @param clientX Mouse click screen X coordinate
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { pick } from 'lodash';
|
||||||
import { useCallback, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
import { Operator } from '../constant';
|
import { Operator } from '../constant';
|
||||||
import useGraphStore from '../store';
|
import useGraphStore from '../store';
|
||||||
@ -113,7 +114,7 @@ export const usePlaceholderManager = (reactFlowInstance: any) => {
|
|||||||
if (newNode) {
|
if (newNode) {
|
||||||
updateNode({
|
updateNode({
|
||||||
...newNode,
|
...newNode,
|
||||||
position: placeholderNode.position,
|
...pick(placeholderNode, ['position', 'parentId', 'extent']),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user