From a55a7603ddd12273fb8bd3246a50dc2ad15ddc2d Mon Sep 17 00:00:00 2001 From: StyleZhang Date: Wed, 13 Mar 2024 11:53:21 +0800 Subject: [PATCH] split hooks --- web/app/components/workflow/features.tsx | 4 +- web/app/components/workflow/header/index.tsx | 8 +- .../workflow/header/run-and-history.tsx | 6 +- web/app/components/workflow/hooks/index.ts | 7 + .../workflow/hooks/use-edges-interactions.ts | 118 +++++ .../workflow/hooks/use-node-data-update.ts | 43 ++ .../workflow/hooks/use-nodes-data.ts | 27 ++ .../use-nodes-interactions.ts} | 450 +----------------- .../workflow/hooks/use-nodes-sync-draft.ts | 85 ++++ .../workflow/hooks/use-workflow-run.ts | 103 ++++ .../components/workflow/hooks/use-workflow.ts | 126 +++++ web/app/components/workflow/index.tsx | 12 +- .../nodes/_base/components/next-step/add.tsx | 4 +- .../nodes/_base/components/next-step/item.tsx | 4 +- .../nodes/_base/components/node-control.tsx | 4 +- .../nodes/_base/components/node-handle.tsx | 6 +- .../panel-operator/change-block.tsx | 4 +- .../_base/components/panel-operator/index.tsx | 4 +- .../nodes/_base/hooks/use-node-crud.ts | 6 +- .../nodes/_base/hooks/use-one-step-run.ts | 4 +- .../components/workflow/nodes/_base/panel.tsx | 19 +- .../components/class-list.tsx | 4 +- .../workflow/operator/zoom-in-out.tsx | 4 +- .../workflow/panel/debug-and-preview/hooks.ts | 6 +- .../workflow/panel/inputs-panel.tsx | 19 +- 25 files changed, 586 insertions(+), 491 deletions(-) create mode 100644 web/app/components/workflow/hooks/index.ts create mode 100644 web/app/components/workflow/hooks/use-edges-interactions.ts create mode 100644 web/app/components/workflow/hooks/use-node-data-update.ts create mode 100644 web/app/components/workflow/hooks/use-nodes-data.ts rename web/app/components/workflow/{hooks.ts => hooks/use-nodes-interactions.ts} (51%) create mode 100644 web/app/components/workflow/hooks/use-nodes-sync-draft.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run.ts create mode 100644 web/app/components/workflow/hooks/use-workflow.ts diff --git a/web/app/components/workflow/features.tsx b/web/app/components/workflow/features.tsx index eba26a70c3..3da33f8c14 100644 --- a/web/app/components/workflow/features.tsx +++ b/web/app/components/workflow/features.tsx @@ -4,7 +4,7 @@ import { } from 'react' import { useTranslation } from 'react-i18next' import { useStore } from './store' -import { useWorkflow } from './hooks' +import { useNodesSyncDraft } from './hooks' import { XClose } from '@/app/components/base/icons/src/vender/line/general' import { FeaturesChoose, @@ -14,7 +14,7 @@ import { const Features = () => { const { t } = useTranslation() const setShowFeaturesPanel = useStore(state => state.setShowFeaturesPanel) - const { handleSyncWorkflowDraft } = useWorkflow() + const { handleSyncWorkflowDraft } = useNodesSyncDraft() const handleFeaturesChange = useCallback(() => { handleSyncWorkflowDraft() diff --git a/web/app/components/workflow/header/index.tsx b/web/app/components/workflow/header/index.tsx index 8cae9fff03..6e428ef6e6 100644 --- a/web/app/components/workflow/header/index.tsx +++ b/web/app/components/workflow/header/index.tsx @@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next' import { useStore } from '../store' import { useIsChatMode, - useWorkflow, + useWorkflowRun, } from '../hooks' import RunAndHistory from './run-and-history' import EditingTitle from './editing-title' @@ -24,15 +24,15 @@ const Header: FC = () => { const appSidebarExpand = useAppStore(s => s.appSidebarExpand) const isChatMode = useIsChatMode() const runningStatus = useStore(s => s.runningStatus) - const { handleRunInit } = useWorkflow() + const { handleRunSetting } = useWorkflowRun() const handleShowFeatures = useCallback(() => { useStore.setState({ showFeaturesPanel: true }) }, []) const handleGoBackToEdit = useCallback(() => { - handleRunInit(true) - }, [handleRunInit]) + handleRunSetting(true) + }, [handleRunSetting]) return (
{ const { t } = useTranslation() - const { handleRunInit } = useWorkflow() + const { handleRunSetting } = useWorkflowRun() const runningStatus = useStore(s => s.runningStatus) const handleClick = () => { - handleRunInit() + handleRunSetting() } return ( diff --git a/web/app/components/workflow/hooks/index.ts b/web/app/components/workflow/hooks/index.ts new file mode 100644 index 0000000000..f1caffef8d --- /dev/null +++ b/web/app/components/workflow/hooks/index.ts @@ -0,0 +1,7 @@ +export * from './use-edges-interactions' +export * from './use-node-data-update' +export * from './use-nodes-interactions' +export * from './use-nodes-data' +export * from './use-nodes-sync-draft' +export * from './use-workflow' +export * from './use-workflow-run' diff --git a/web/app/components/workflow/hooks/use-edges-interactions.ts b/web/app/components/workflow/hooks/use-edges-interactions.ts new file mode 100644 index 0000000000..160d4367f4 --- /dev/null +++ b/web/app/components/workflow/hooks/use-edges-interactions.ts @@ -0,0 +1,118 @@ +import { useCallback } from 'react' +import produce from 'immer' +import type { + EdgeMouseHandler, + OnEdgesChange, +} from 'reactflow' +import { useStoreApi } from 'reactflow' +import { useStore } from '../store' +import { useNodesSyncDraft } from './use-nodes-sync-draft' + +export const useEdgesInteractions = () => { + const store = useStoreApi() + const { handleSyncWorkflowDraft } = useNodesSyncDraft() + + const handleEdgeEnter = useCallback((_, edge) => { + const { runningStatus } = useStore.getState() + + if (runningStatus) + return + + const { + edges, + setEdges, + } = store.getState() + const newEdges = produce(edges, (draft) => { + const currentEdge = draft.find(e => e.id === edge.id)! + + currentEdge.data = { ...currentEdge.data, _hovering: true } + }) + setEdges(newEdges) + }, [store]) + + const handleEdgeLeave = useCallback((_, edge) => { + const { runningStatus } = useStore.getState() + + if (runningStatus) + return + + const { + edges, + setEdges, + } = store.getState() + const newEdges = produce(edges, (draft) => { + const currentEdge = draft.find(e => e.id === edge.id)! + + currentEdge.data = { ...currentEdge.data, _hovering: false } + }) + setEdges(newEdges) + }, [store]) + + const handleEdgeDeleteByDeleteBranch = useCallback((nodeId: string, branchId: string) => { + const { runningStatus } = useStore.getState() + + if (runningStatus) + return + + const { + edges, + setEdges, + } = store.getState() + const newEdges = produce(edges, (draft) => { + const index = draft.findIndex(edge => edge.source === nodeId && edge.sourceHandle === branchId) + + if (index > -1) + draft.splice(index, 1) + }) + setEdges(newEdges) + handleSyncWorkflowDraft() + }, [store, handleSyncWorkflowDraft]) + + const handleEdgeDelete = useCallback(() => { + const { runningStatus } = useStore.getState() + + if (runningStatus) + return + + const { + edges, + setEdges, + } = store.getState() + const newEdges = produce(edges, (draft) => { + const index = draft.findIndex(edge => edge.selected) + + if (index > -1) + draft.splice(index, 1) + }) + setEdges(newEdges) + handleSyncWorkflowDraft() + }, [store, handleSyncWorkflowDraft]) + + const handleEdgesChange = useCallback((changes) => { + const { runningStatus } = useStore.getState() + + if (runningStatus) + return + + const { + edges, + setEdges, + } = store.getState() + + const newEdges = produce(edges, (draft) => { + changes.forEach((change) => { + if (change.type === 'select') + draft.find(edge => edge.id === change.id)!.selected = change.selected + }) + }) + setEdges(newEdges) + }, [store]) + + return { + handleEdgeEnter, + handleEdgeLeave, + handleEdgeDeleteByDeleteBranch, + handleEdgeDelete, + handleEdgesChange, + } +} diff --git a/web/app/components/workflow/hooks/use-node-data-update.ts b/web/app/components/workflow/hooks/use-node-data-update.ts new file mode 100644 index 0000000000..3f8175683c --- /dev/null +++ b/web/app/components/workflow/hooks/use-node-data-update.ts @@ -0,0 +1,43 @@ +import { useCallback } from 'react' +import produce from 'immer' +import { useStoreApi } from 'reactflow' +import { useStore } from '../store' +import { useNodesSyncDraft } from './use-nodes-sync-draft' + +type NodeDataUpdatePayload = { + id: string + data: Record +} + +export const useNodeDataUpdate = () => { + const store = useStoreApi() + const { handleSyncWorkflowDraft } = useNodesSyncDraft() + + const handleNodeDataUpdate = useCallback(({ id, data }: NodeDataUpdatePayload) => { + const { + getNodes, + setNodes, + } = store.getState() + const newNodes = produce(getNodes(), (draft) => { + const currentNode = draft.find(node => node.id === id)! + + currentNode.data = { ...currentNode.data, ...data } + }) + setNodes(newNodes) + }, [store]) + + const handleNodeDataUpdateWithSyncDraft = useCallback((payload: NodeDataUpdatePayload) => { + const { runningStatus } = useStore.getState() + + if (runningStatus) + return + + handleNodeDataUpdate(payload) + handleSyncWorkflowDraft(true) + }, [handleSyncWorkflowDraft, handleNodeDataUpdate]) + + return { + handleNodeDataUpdate, + handleNodeDataUpdateWithSyncDraft, + } +} diff --git a/web/app/components/workflow/hooks/use-nodes-data.ts b/web/app/components/workflow/hooks/use-nodes-data.ts new file mode 100644 index 0000000000..29920c76de --- /dev/null +++ b/web/app/components/workflow/hooks/use-nodes-data.ts @@ -0,0 +1,27 @@ +import { useTranslation } from 'react-i18next' +import produce from 'immer' +import type { BlockEnum } from '../types' +import { + NODES_EXTRA_DATA, + NODES_INITIAL_DATA, +} from '../constants' + +export const useNodesInitialData = () => { + const { t } = useTranslation() + + return produce(NODES_INITIAL_DATA, (draft) => { + Object.keys(draft).forEach((key) => { + draft[key as BlockEnum].title = t(`workflow.blocks.${key}`) + }) + }) +} + +export const useNodesExtraData = () => { + const { t } = useTranslation() + + return produce(NODES_EXTRA_DATA, (draft) => { + Object.keys(draft).forEach((key) => { + draft[key as BlockEnum].about = t(`workflow.blocksAbout.${key}`) + }) + }) +} diff --git a/web/app/components/workflow/hooks.ts b/web/app/components/workflow/hooks/use-nodes-interactions.ts similarity index 51% rename from web/app/components/workflow/hooks.ts rename to web/app/components/workflow/hooks/use-nodes-interactions.ts index 60d3631a70..bec4edb915 100644 --- a/web/app/components/workflow/hooks.ts +++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts @@ -1,162 +1,34 @@ import { useCallback } from 'react' -import { useTranslation } from 'react-i18next' import produce from 'immer' -import { useDebounceFn } from 'ahooks' import type { - EdgeMouseHandler, NodeDragHandler, NodeMouseHandler, OnConnect, - OnEdgesChange, - Viewport, } from 'reactflow' import { Position, getConnectedEdges, getIncomers, getOutgoers, - useReactFlow, useStoreApi, } from 'reactflow' -import type { Node } from './types' +import type { ToolDefaultValue } from '../block-selector/types' +import type { + Node, +} from '../types' +import { BlockEnum } from '../types' +import { useStore } from '../store' import { - BlockEnum, - NodeRunningStatus, - WorkflowRunningStatus, -} from './types' -import { - NODES_EXTRA_DATA, - NODES_INITIAL_DATA, NODE_WIDTH_X_OFFSET, Y_OFFSET, -} from './constants' -import { - getLayoutByDagre, -} from './utils' -import { useStore } from './store' -import type { ToolDefaultValue } from './block-selector/types' -import { syncWorkflowDraft } from '@/service/workflow' -import { useFeaturesStore } from '@/app/components/base/features/hooks' -import { useStore as useAppStore } from '@/app/components/app/store' -import { ssePost } from '@/service/base' -import type { IOtherOptions } from '@/service/base' +} from '../constants' +import { useNodesInitialData } from './use-nodes-data' +import { useNodesSyncDraft } from './use-nodes-sync-draft' -export const useIsChatMode = () => { - const appDetail = useAppStore(s => s.appDetail) - - return appDetail?.mode === 'advanced-chat' -} - -export const useNodesInitialData = () => { - const { t } = useTranslation() - - return produce(NODES_INITIAL_DATA, (draft) => { - Object.keys(draft).forEach((key) => { - draft[key as BlockEnum].title = t(`workflow.blocks.${key}`) - }) - }) -} - -export const useNodesExtraData = () => { - const { t } = useTranslation() - - return produce(NODES_EXTRA_DATA, (draft) => { - Object.keys(draft).forEach((key) => { - draft[key as BlockEnum].about = t(`workflow.blocksAbout.${key}`) - }) - }) -} - -export const useWorkflow = () => { +export const useNodesInteractions = () => { const store = useStoreApi() - const reactFlow = useReactFlow() const nodesInitialData = useNodesInitialData() - const featuresStore = useFeaturesStore() - - const shouldDebouncedSyncWorkflowDraft = useCallback(() => { - const { - getNodes, - edges, - } = store.getState() - const { getViewport } = reactFlow - const appId = useAppStore.getState().appDetail?.id - - if (appId) { - const features = featuresStore!.getState().features - const producedNodes = produce(getNodes(), (draft) => { - draft.forEach((node) => { - Object.keys(node.data).forEach((key) => { - if (key.startsWith('_')) - delete node.data[key] - }) - }) - }) - const producedEdges = produce(edges, (draft) => { - draft.forEach((edge) => { - delete edge.data - }) - }) - syncWorkflowDraft({ - url: `/apps/${appId}/workflows/draft`, - params: { - graph: { - nodes: producedNodes, - edges: producedEdges, - viewport: getViewport(), - }, - features: { - opening_statement: features.opening.opening_statement, - suggested_questions: features.opening.suggested_questions, - suggested_questions_after_answer: features.suggested, - text_to_speech: features.text2speech, - speech_to_text: features.speech2text, - retriever_resource: features.citation, - sensitive_word_avoidance: features.moderation, - }, - }, - }).then((res) => { - useStore.setState({ draftUpdatedAt: res.updated_at }) - }) - } - }, [store, reactFlow, featuresStore]) - - const { run: debouncedSyncWorkflowDraft } = useDebounceFn(shouldDebouncedSyncWorkflowDraft, { - wait: 2000, - trailing: true, - }) - - const handleSyncWorkflowDraft = useCallback((shouldDelay?: boolean) => { - if (shouldDelay) - debouncedSyncWorkflowDraft() - else - shouldDebouncedSyncWorkflowDraft() - }, [debouncedSyncWorkflowDraft, shouldDebouncedSyncWorkflowDraft]) - - const handleLayout = useCallback(async () => { - const { - getNodes, - edges, - setNodes, - } = store.getState() - - const layout = getLayoutByDagre(getNodes(), edges) - - const newNodes = produce(getNodes(), (draft) => { - draft.forEach((node) => { - const nodeWithPosition = layout.node(node.id) - node.position = { - x: nodeWithPosition.x, - y: nodeWithPosition.y, - } - }) - }) - setNodes(newNodes) - }, [store]) - - const handleSetViewport = useCallback((viewPort: Viewport) => { - reactFlow.setViewport(viewPort) - handleSyncWorkflowDraft() - }, [reactFlow, handleSyncWorkflowDraft]) + const { handleSyncWorkflowDraft } = useNodesSyncDraft() const handleNodeDragStart = useCallback(() => { const { @@ -164,8 +36,10 @@ export const useWorkflow = () => { setIsDragging, } = useStore.getState() - if (!runningStatus) - setIsDragging(true) + if (runningStatus) + return + + setIsDragging(true) }, []) const handleNodeDrag = useCallback((e, node: Node) => { @@ -433,25 +307,6 @@ export const useWorkflow = () => { handleSyncWorkflowDraft() }, [store, handleSyncWorkflowDraft]) - const handleNodeDataUpdate = useCallback(({ id, data }: { id: string; data: Record }) => { - const { runningStatus } = useStore.getState() - - if (runningStatus) - return - - const { - getNodes, - setNodes, - } = store.getState() - const newNodes = produce(getNodes(), (draft) => { - const currentNode = draft.find(node => node.id === id)! - - currentNode.data = { ...currentNode.data, ...data } - }) - setNodes(newNodes) - handleSyncWorkflowDraft(true) - }, [store, handleSyncWorkflowDraft]) - const handleNodeAddNext = useCallback(( currentNodeId: string, nodeType: BlockEnum, @@ -636,196 +491,7 @@ export const useWorkflow = () => { } }, [store, nodesInitialData, handleSyncWorkflowDraft]) - const handleEdgeEnter = useCallback((_, edge) => { - const { runningStatus } = useStore.getState() - - if (runningStatus) - return - - const { - edges, - setEdges, - } = store.getState() - const newEdges = produce(edges, (draft) => { - const currentEdge = draft.find(e => e.id === edge.id)! - - currentEdge.data = { ...currentEdge.data, _hovering: true } - }) - setEdges(newEdges) - }, [store]) - - const handleEdgeLeave = useCallback((_, edge) => { - const { runningStatus } = useStore.getState() - - if (runningStatus) - return - - const { - edges, - setEdges, - } = store.getState() - const newEdges = produce(edges, (draft) => { - const currentEdge = draft.find(e => e.id === edge.id)! - - currentEdge.data = { ...currentEdge.data, _hovering: false } - }) - setEdges(newEdges) - }, [store]) - - const handleEdgeDeleteByDeleteBranch = useCallback((nodeId: string, branchId: string) => { - const { runningStatus } = useStore.getState() - - if (runningStatus) - return - - const { - edges, - setEdges, - } = store.getState() - const newEdges = produce(edges, (draft) => { - const index = draft.findIndex(edge => edge.source === nodeId && edge.sourceHandle === branchId) - - if (index > -1) - draft.splice(index, 1) - }) - setEdges(newEdges) - handleSyncWorkflowDraft() - }, [store, handleSyncWorkflowDraft]) - - const handleEdgeDelete = useCallback(() => { - const { runningStatus } = useStore.getState() - - if (runningStatus) - return - - const { - edges, - setEdges, - } = store.getState() - const newEdges = produce(edges, (draft) => { - const index = draft.findIndex(edge => edge.selected) - - if (index > -1) - draft.splice(index, 1) - }) - setEdges(newEdges) - handleSyncWorkflowDraft() - }, [store, handleSyncWorkflowDraft]) - - const handleEdgesChange = useCallback((changes) => { - const { runningStatus } = useStore.getState() - - if (runningStatus) - return - - const { - edges, - setEdges, - } = store.getState() - - const newEdges = produce(edges, (draft) => { - changes.forEach((change) => { - if (change.type === 'select') - draft.find(edge => edge.id === change.id)!.selected = change.selected - }) - }) - setEdges(newEdges) - }, [store]) - - const handleRunInit = useCallback((shouldClear?: boolean) => { - useStore.setState({ runningStatus: shouldClear ? undefined : WorkflowRunningStatus.Waiting }) - const { setNodes, getNodes } = store.getState() - const newNodes = produce(getNodes(), (draft) => { - draft.forEach((node) => { - node.data._runningStatus = shouldClear ? undefined : NodeRunningStatus.Waiting - }) - }) - setNodes(newNodes) - }, [store]) - - const getTreeLeafNodes = useCallback(() => { - const { - getNodes, - edges, - } = store.getState() - const nodes = getNodes() - const startNode = nodes.find(node => node.data.type === BlockEnum.Start) - - if (!startNode) - return [] - - const list: Node[] = [] - const preOrder = (root: Node, callback: (node: Node) => void) => { - const outgoers = getOutgoers(root, nodes, edges) - - if (outgoers.length) { - outgoers.forEach((outgoer) => { - preOrder(outgoer, callback) - }) - } - else { - callback(root) - } - } - preOrder(startNode, (node) => { - list.push(node) - }) - - return list.filter((item) => { - if (item.data.type === BlockEnum.IfElse) - return false - - if (item.data.type === BlockEnum.QuestionClassifier) - return false - - return true - }) - }, [store]) - - const getBeforeNodesInSameBranch = useCallback((nodeId: string) => { - const { - getNodes, - edges, - } = store.getState() - const nodes = getNodes() - const currentNode = nodes.find(node => node.id === nodeId)! - const list: Node[] = [] - - const traverse = (root: Node, callback: (node: Node) => void) => { - const incomers = getIncomers(root, nodes, edges) - - if (incomers.length) { - incomers.forEach((node) => { - callback(node) - traverse(node, callback) - }) - } - } - traverse(currentNode, (node) => { - list.push(node) - }) - - const length = list.length - if (length && list.some(item => item.data.type === BlockEnum.Start)) { - return list.reverse().filter((item) => { - if (item.data.type === BlockEnum.IfElse) - return false - - if (item.data.type === BlockEnum.QuestionClassifier) - return false - - return true - }) - } - - return [] - }, [store]) - return { - handleSyncWorkflowDraft, - handleLayout, - handleSetViewport, - handleNodeDragStart, handleNodeDrag, handleNodeDragStop, @@ -835,94 +501,8 @@ export const useWorkflow = () => { handleNodeClick, handleNodeConnect, handleNodeDelete, - handleNodeDataUpdate, handleNodeAddNext, handleNodeAddPrev, handleNodeChange, - - handleEdgeEnter, - handleEdgeLeave, - handleEdgeDeleteByDeleteBranch, - handleEdgeDelete, - handleEdgesChange, - - handleRunInit, - getTreeLeafNodes, - getBeforeNodesInSameBranch, } } - -export const useWorkflowRun = () => { - const store = useStoreApi() - const reactflow = useReactFlow() - - const run = useCallback((params: any, callback?: IOtherOptions) => { - const { - getNodes, - setNodes, - } = store.getState() - const appDetail = useAppStore.getState().appDetail - - let url = '' - if (appDetail?.mode === 'advanced-chat') - url = `/apps/${appDetail.id}/advanced-chat/workflows/draft/run` - - if (appDetail?.mode === 'workflow') - url = `/apps/${appDetail.id}/workflows/draft/run` - - ssePost( - url, - { - body: params, - }, - { - onWorkflowStarted: ({ task_id, workflow_run_id, sequence_number }) => { - useStore.setState({ runningStatus: WorkflowRunningStatus.Running }) - useStore.setState({ taskId: task_id }) - useStore.setState({ currentSequenceNumber: sequence_number }) - useStore.setState({ workflowRunId: workflow_run_id }) - const newNodes = produce(getNodes(), (draft) => { - draft.forEach((node) => { - node.data._runningStatus = NodeRunningStatus.Waiting - }) - }) - setNodes(newNodes) - }, - onWorkflowFinished: ({ data }) => { - useStore.setState({ runningStatus: data.status as WorkflowRunningStatus }) - }, - onNodeStarted: ({ data }) => { - const nodes = getNodes() - const { - getViewport, - setViewport, - } = reactflow - const viewport = getViewport() - const currentNodeIndex = nodes.findIndex(node => node.id === data.node_id) - const position = nodes[currentNodeIndex].position - const zoom = 1 - setViewport({ - zoom, - x: 200 / viewport.zoom - position.x, - y: 200 / viewport.zoom - position.y, - }) - const newNodes = produce(nodes, (draft) => { - draft[currentNodeIndex].data._runningStatus = NodeRunningStatus.Running - }) - setNodes(newNodes) - }, - onNodeFinished: ({ data }) => { - const newNodes = produce(getNodes(), (draft) => { - const currentNode = draft.find(node => node.id === data.node_id)! - - currentNode.data._runningStatus = data.status - }) - setNodes(newNodes) - }, - ...callback, - }, - ) - }, [store, reactflow]) - - return run -} diff --git a/web/app/components/workflow/hooks/use-nodes-sync-draft.ts b/web/app/components/workflow/hooks/use-nodes-sync-draft.ts new file mode 100644 index 0000000000..c96a451182 --- /dev/null +++ b/web/app/components/workflow/hooks/use-nodes-sync-draft.ts @@ -0,0 +1,85 @@ +import { useCallback } from 'react' +import produce from 'immer' +import { useDebounceFn } from 'ahooks' +import { + useReactFlow, + useStoreApi, +} from 'reactflow' +import { useStore } from '../store' +import { syncWorkflowDraft } from '@/service/workflow' +import { useFeaturesStore } from '@/app/components/base/features/hooks' +import { useStore as useAppStore } from '@/app/components/app/store' + +export const useNodesSyncDraft = () => { + const store = useStoreApi() + const reactFlow = useReactFlow() + const featuresStore = useFeaturesStore() + + const shouldDebouncedSyncWorkflowDraft = useCallback(() => { + const { + getNodes, + edges, + } = store.getState() + const { getViewport } = reactFlow + const appId = useAppStore.getState().appDetail?.id + + if (appId) { + const features = featuresStore!.getState().features + const producedNodes = produce(getNodes(), (draft) => { + draft.forEach((node) => { + Object.keys(node.data).forEach((key) => { + if (key.startsWith('_')) + delete node.data[key] + }) + }) + }) + const producedEdges = produce(edges, (draft) => { + draft.forEach((edge) => { + delete edge.data + }) + }) + syncWorkflowDraft({ + url: `/apps/${appId}/workflows/draft`, + params: { + graph: { + nodes: producedNodes, + edges: producedEdges, + viewport: getViewport(), + }, + features: { + opening_statement: features.opening.opening_statement, + suggested_questions: features.opening.suggested_questions, + suggested_questions_after_answer: features.suggested, + text_to_speech: features.text2speech, + speech_to_text: features.speech2text, + retriever_resource: features.citation, + sensitive_word_avoidance: features.moderation, + }, + }, + }).then((res) => { + useStore.setState({ draftUpdatedAt: res.updated_at }) + }) + } + }, [store, reactFlow, featuresStore]) + + const { run: debouncedSyncWorkflowDraft } = useDebounceFn(shouldDebouncedSyncWorkflowDraft, { + wait: 2000, + trailing: true, + }) + + const handleSyncWorkflowDraft = useCallback((shouldDelay?: boolean) => { + const { runningStatus } = useStore.getState() + + if (runningStatus) + return + + if (shouldDelay) + debouncedSyncWorkflowDraft() + else + shouldDebouncedSyncWorkflowDraft() + }, [debouncedSyncWorkflowDraft, shouldDebouncedSyncWorkflowDraft]) + + return { + handleSyncWorkflowDraft, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run.ts b/web/app/components/workflow/hooks/use-workflow-run.ts new file mode 100644 index 0000000000..6091432431 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run.ts @@ -0,0 +1,103 @@ +import { useCallback } from 'react' +import { + useReactFlow, + useStoreApi, +} from 'reactflow' +import produce from 'immer' +import { useStore } from '../store' +import { + NodeRunningStatus, + WorkflowRunningStatus, +} from '../types' +import { useStore as useAppStore } from '@/app/components/app/store' +import type { IOtherOptions } from '@/service/base' +import { ssePost } from '@/service/base' + +export const useWorkflowRun = () => { + const store = useStoreApi() + const reactflow = useReactFlow() + + const handleRunSetting = useCallback((shouldClear?: boolean) => { + useStore.setState({ runningStatus: shouldClear ? undefined : WorkflowRunningStatus.Waiting }) + const { setNodes, getNodes } = store.getState() + const newNodes = produce(getNodes(), (draft) => { + draft.forEach((node) => { + node.data._runningStatus = shouldClear ? undefined : NodeRunningStatus.Waiting + }) + }) + setNodes(newNodes) + }, [store]) + + const handleRun = useCallback((params: any, callback?: IOtherOptions) => { + const { + getNodes, + setNodes, + } = store.getState() + const appDetail = useAppStore.getState().appDetail + + let url = '' + if (appDetail?.mode === 'advanced-chat') + url = `/apps/${appDetail.id}/advanced-chat/workflows/draft/run` + + if (appDetail?.mode === 'workflow') + url = `/apps/${appDetail.id}/workflows/draft/run` + + ssePost( + url, + { + body: params, + }, + { + onWorkflowStarted: ({ task_id, workflow_run_id, sequence_number }) => { + useStore.setState({ runningStatus: WorkflowRunningStatus.Running }) + useStore.setState({ taskId: task_id }) + useStore.setState({ currentSequenceNumber: sequence_number }) + useStore.setState({ workflowRunId: workflow_run_id }) + const newNodes = produce(getNodes(), (draft) => { + draft.forEach((node) => { + node.data._runningStatus = NodeRunningStatus.Waiting + }) + }) + setNodes(newNodes) + }, + onWorkflowFinished: ({ data }) => { + useStore.setState({ runningStatus: data.status as WorkflowRunningStatus }) + }, + onNodeStarted: ({ data }) => { + const nodes = getNodes() + const { + getViewport, + setViewport, + } = reactflow + const viewport = getViewport() + const currentNodeIndex = nodes.findIndex(node => node.id === data.node_id) + const position = nodes[currentNodeIndex].position + const zoom = 1 + setViewport({ + zoom, + x: 200 / viewport.zoom - position.x, + y: 200 / viewport.zoom - position.y, + }) + const newNodes = produce(nodes, (draft) => { + draft[currentNodeIndex].data._runningStatus = NodeRunningStatus.Running + }) + setNodes(newNodes) + }, + onNodeFinished: ({ data }) => { + const newNodes = produce(getNodes(), (draft) => { + const currentNode = draft.find(node => node.id === data.node_id)! + + currentNode.data._runningStatus = data.status + }) + setNodes(newNodes) + }, + ...callback, + }, + ) + }, [store, reactflow]) + + return { + handleRunSetting, + handleRun, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow.ts b/web/app/components/workflow/hooks/use-workflow.ts new file mode 100644 index 0000000000..11c58e5a1b --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow.ts @@ -0,0 +1,126 @@ +import { useCallback } from 'react' +import produce from 'immer' +import { + getIncomers, + getOutgoers, + useStoreApi, +} from 'reactflow' +import { getLayoutByDagre } from '../utils' +import type { Node } from '../types' +import { BlockEnum } from '../types' +import { useStore as useAppStore } from '@/app/components/app/store' + +export const useIsChatMode = () => { + const appDetail = useAppStore(s => s.appDetail) + + return appDetail?.mode === 'advanced-chat' +} + +export const useWorkflow = () => { + const store = useStoreApi() + + const handleLayout = useCallback(async () => { + const { + getNodes, + edges, + setNodes, + } = store.getState() + + const layout = getLayoutByDagre(getNodes(), edges) + + const newNodes = produce(getNodes(), (draft) => { + draft.forEach((node) => { + const nodeWithPosition = layout.node(node.id) + node.position = { + x: nodeWithPosition.x, + y: nodeWithPosition.y, + } + }) + }) + setNodes(newNodes) + }, [store]) + + const getTreeLeafNodes = useCallback(() => { + const { + getNodes, + edges, + } = store.getState() + const nodes = getNodes() + const startNode = nodes.find(node => node.data.type === BlockEnum.Start) + + if (!startNode) + return [] + + const list: Node[] = [] + const preOrder = (root: Node, callback: (node: Node) => void) => { + const outgoers = getOutgoers(root, nodes, edges) + + if (outgoers.length) { + outgoers.forEach((outgoer) => { + preOrder(outgoer, callback) + }) + } + else { + callback(root) + } + } + preOrder(startNode, (node) => { + list.push(node) + }) + + return list.filter((item) => { + if (item.data.type === BlockEnum.IfElse) + return false + + if (item.data.type === BlockEnum.QuestionClassifier) + return false + + return true + }) + }, [store]) + + const getBeforeNodesInSameBranch = useCallback((nodeId: string) => { + const { + getNodes, + edges, + } = store.getState() + const nodes = getNodes() + const currentNode = nodes.find(node => node.id === nodeId)! + const list: Node[] = [] + + const traverse = (root: Node, callback: (node: Node) => void) => { + const incomers = getIncomers(root, nodes, edges) + + if (incomers.length) { + incomers.forEach((node) => { + callback(node) + traverse(node, callback) + }) + } + } + traverse(currentNode, (node) => { + list.push(node) + }) + + const length = list.length + if (length && list.some(item => item.data.type === BlockEnum.Start)) { + return list.reverse().filter((item) => { + if (item.data.type === BlockEnum.IfElse) + return false + + if (item.data.type === BlockEnum.QuestionClassifier) + return false + + return true + }) + } + + return [] + }, [store]) + + return { + handleLayout, + getTreeLeafNodes, + getBeforeNodesInSameBranch, + } +} diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 411f3376cf..fe12a32ed3 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -20,8 +20,10 @@ import type { Node, } from './types' import { + useEdgesInteractions, useNodesInitialData, - useWorkflow, + useNodesInteractions, + useNodesSyncDraft, } from './hooks' import Header from './header' import CustomNode from './nodes' @@ -65,6 +67,7 @@ const Workflow: FC = memo(({ }) => { const showFeaturesPanel = useStore(state => state.showFeaturesPanel) const runningStatus = useStore(s => s.runningStatus) + const { handleSyncWorkflowDraft } = useNodesSyncDraft() useEffect(() => { setAutoFreeze(false) @@ -75,8 +78,6 @@ const Workflow: FC = memo(({ }, []) const { - handleSyncWorkflowDraft, - handleNodeDragStart, handleNodeDrag, handleNodeDragStop, @@ -84,12 +85,13 @@ const Workflow: FC = memo(({ handleNodeLeave, handleNodeClick, handleNodeConnect, - + } = useNodesInteractions() + const { handleEdgeEnter, handleEdgeLeave, handleEdgeDelete, handleEdgesChange, - } = useWorkflow() + } = useEdgesInteractions() useOnViewportChange({ onEnd: () => handleSyncWorkflowDraft(), diff --git a/web/app/components/workflow/nodes/_base/components/next-step/add.tsx b/web/app/components/workflow/nodes/_base/components/next-step/add.tsx index 7d26a5fa3c..8c4790f751 100644 --- a/web/app/components/workflow/nodes/_base/components/next-step/add.tsx +++ b/web/app/components/workflow/nodes/_base/components/next-step/add.tsx @@ -3,7 +3,7 @@ import { useCallback, } from 'react' import { useTranslation } from 'react-i18next' -import { useWorkflow } from '@/app/components/workflow/hooks' +import { useNodesInteractions } from '@/app/components/workflow/hooks' import BlockSelector from '@/app/components/workflow/block-selector' import { Plus } from '@/app/components/base/icons/src/vender/line/general' import type { OnSelectBlock } from '@/app/components/workflow/types' @@ -19,7 +19,7 @@ const Add = ({ branchName, }: AddProps) => { const { t } = useTranslation() - const { handleNodeAddNext } = useWorkflow() + const { handleNodeAddNext } = useNodesInteractions() const handleSelect = useCallback((type, toolDefaultValue) => { handleNodeAddNext(nodeId, type, sourceHandle, toolDefaultValue) diff --git a/web/app/components/workflow/nodes/_base/components/next-step/item.tsx b/web/app/components/workflow/nodes/_base/components/next-step/item.tsx index 82630a83fd..7a112a1403 100644 --- a/web/app/components/workflow/nodes/_base/components/next-step/item.tsx +++ b/web/app/components/workflow/nodes/_base/components/next-step/item.tsx @@ -9,7 +9,7 @@ import type { } from '@/app/components/workflow/types' import BlockIcon from '@/app/components/workflow/block-icon' import BlockSelector from '@/app/components/workflow/block-selector' -import { useWorkflow } from '@/app/components/workflow/hooks' +import { useNodesInteractions } from '@/app/components/workflow/hooks' import Button from '@/app/components/base/button' type ItemProps = { @@ -25,7 +25,7 @@ const Item = ({ data, }: ItemProps) => { const { t } = useTranslation() - const { handleNodeChange } = useWorkflow() + const { handleNodeChange } = useNodesInteractions() const handleSelect = useCallback((type, toolDefaultValue) => { handleNodeChange(nodeId, type, sourceHandle, toolDefaultValue) }, [nodeId, sourceHandle, handleNodeChange]) diff --git a/web/app/components/workflow/nodes/_base/components/node-control.tsx b/web/app/components/workflow/nodes/_base/components/node-control.tsx index c9b266ff93..0dd5836c6b 100644 --- a/web/app/components/workflow/nodes/_base/components/node-control.tsx +++ b/web/app/components/workflow/nodes/_base/components/node-control.tsx @@ -5,7 +5,7 @@ import { useState, } from 'react' import { useTranslation } from 'react-i18next' -import { useWorkflow } from '../../../hooks' +import { useNodeDataUpdate } from '../../../hooks' import type { Node } from '../../../types' import { canRunBySingle } from '../../../utils' import PanelOperator from './panel-operator' @@ -22,7 +22,7 @@ const NodeControl: FC = ({ }) => { const { t } = useTranslation() const [open, setOpen] = useState(false) - const { handleNodeDataUpdate } = useWorkflow() + const { handleNodeDataUpdate } = useNodeDataUpdate() const handleOpenChange = useCallback((newOpen: boolean) => { setOpen(newOpen) diff --git a/web/app/components/workflow/nodes/_base/components/node-handle.tsx b/web/app/components/workflow/nodes/_base/components/node-handle.tsx index 7efe521843..164ec9822a 100644 --- a/web/app/components/workflow/nodes/_base/components/node-handle.tsx +++ b/web/app/components/workflow/nodes/_base/components/node-handle.tsx @@ -14,7 +14,7 @@ import { BlockEnum } from '../../../types' import type { Node } from '../../../types' import BlockSelector from '../../../block-selector' import type { ToolDefaultValue } from '../../../block-selector/types' -import { useWorkflow } from '../../../hooks' +import { useNodesInteractions } from '../../../hooks' type NodeHandleProps = { handleId: string @@ -30,7 +30,7 @@ export const NodeTargetHandle = ({ nodeSelectorClassName, }: NodeHandleProps) => { const [open, setOpen] = useState(false) - const { handleNodeAddPrev } = useWorkflow() + const { handleNodeAddPrev } = useNodesInteractions() const edges = useEdges() const connectedEdges = getConnectedEdges([{ id } as Node], edges) const connected = connectedEdges.find(edge => edge.targetHandle === handleId && edge.target === id) @@ -92,7 +92,7 @@ export const NodeSourceHandle = ({ nodeSelectorClassName, }: NodeHandleProps) => { const [open, setOpen] = useState(false) - const { handleNodeAddNext } = useWorkflow() + const { handleNodeAddNext } = useNodesInteractions() const edges = useEdges() const connectedEdges = getConnectedEdges([{ id } as Node], edges) const connected = connectedEdges.find(edge => edge.sourceHandle === handleId && edge.source === id) diff --git a/web/app/components/workflow/nodes/_base/components/panel-operator/change-block.tsx b/web/app/components/workflow/nodes/_base/components/panel-operator/change-block.tsx index c61901a702..c5071f057c 100644 --- a/web/app/components/workflow/nodes/_base/components/panel-operator/change-block.tsx +++ b/web/app/components/workflow/nodes/_base/components/panel-operator/change-block.tsx @@ -4,7 +4,7 @@ import { } from 'react' import { useTranslation } from 'react-i18next' import BlockSelector from '@/app/components/workflow/block-selector' -import { useWorkflow } from '@/app/components/workflow/hooks' +import { useNodesInteractions } from '@/app/components/workflow/hooks' import type { OnSelectBlock } from '@/app/components/workflow/types' type ChangeBlockProps = { @@ -16,7 +16,7 @@ const ChangeBlock = ({ sourceHandle, }: ChangeBlockProps) => { const { t } = useTranslation() - const { handleNodeChange } = useWorkflow() + const { handleNodeChange } = useNodesInteractions() const handleSelect = useCallback((type, toolDefaultValue) => { handleNodeChange(nodeId, type, sourceHandle, toolDefaultValue) diff --git a/web/app/components/workflow/nodes/_base/components/panel-operator/index.tsx b/web/app/components/workflow/nodes/_base/components/panel-operator/index.tsx index 247368ec16..4e4a4a414e 100644 --- a/web/app/components/workflow/nodes/_base/components/panel-operator/index.tsx +++ b/web/app/components/workflow/nodes/_base/components/panel-operator/index.tsx @@ -14,7 +14,7 @@ import ChangeBlock from './change-block' import { useStore } from '@/app/components/workflow/store' import { useNodesExtraData, - useWorkflow, + useNodesInteractions, } from '@/app/components/workflow/hooks' import { DotsHorizontal } from '@/app/components/base/icons/src/vender/line/general' import { @@ -52,7 +52,7 @@ const PanelOperator = ({ const { locale } = useContext(I18n) const language = getLanguage(locale) const edges = useEdges() - const { handleNodeDelete } = useWorkflow() + const { handleNodeDelete } = useNodesInteractions() const nodesExtraData = useNodesExtraData() const toolsets = useStore(s => s.toolsets) const toolsMap = useStore(s => s.toolsMap) diff --git a/web/app/components/workflow/nodes/_base/hooks/use-node-crud.ts b/web/app/components/workflow/nodes/_base/hooks/use-node-crud.ts index e622a8935b..51d2fdb80c 100644 --- a/web/app/components/workflow/nodes/_base/hooks/use-node-crud.ts +++ b/web/app/components/workflow/nodes/_base/hooks/use-node-crud.ts @@ -1,10 +1,10 @@ -import { useWorkflow } from '@/app/components/workflow/hooks' +import { useNodeDataUpdate } from '@/app/components/workflow/hooks' import type { CommonNodeType } from '@/app/components/workflow/types' const useNodeCrud = (id: string, data: CommonNodeType) => { - const { handleNodeDataUpdate } = useWorkflow() + const { handleNodeDataUpdateWithSyncDraft } = useNodeDataUpdate() const setInputs = (newInputs: CommonNodeType) => { - handleNodeDataUpdate({ + handleNodeDataUpdateWithSyncDraft({ id, data: newInputs, }) diff --git a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts index a945beb76b..21ec914a87 100644 --- a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts +++ b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts @@ -1,6 +1,6 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { useWorkflow } from '@/app/components/workflow/hooks' +import { useNodeDataUpdate } from '@/app/components/workflow/hooks' import type { CommonNodeType, InputVar, Variable } from '@/app/components/workflow/types' import { InputVarType, NodeRunningStatus } from '@/app/components/workflow/types' import { useStore as useAppStore } from '@/app/components/app/store' @@ -21,7 +21,7 @@ const useOneStepRun = ({ id, data, defaultRunInputData, isInvalid = () => tru const [runInputData, setRunInputData] = useState>(defaultRunInputData || {}) const [runResult, setRunResult] = useState(null) - const { handleNodeDataUpdate }: { handleNodeDataUpdate: (data: any) => void } = useWorkflow() + const { handleNodeDataUpdate }: { handleNodeDataUpdate: (data: any) => void } = useNodeDataUpdate() const isShowSingleRun = data._isSingleRun const hideSingleRun = () => { handleNodeDataUpdate({ diff --git a/web/app/components/workflow/nodes/_base/panel.tsx b/web/app/components/workflow/nodes/_base/panel.tsx index bbf1aed96b..8f538d2b3e 100644 --- a/web/app/components/workflow/nodes/_base/panel.tsx +++ b/web/app/components/workflow/nodes/_base/panel.tsx @@ -18,7 +18,10 @@ import { XClose, } from '@/app/components/base/icons/src/vender/line/general' import BlockIcon from '@/app/components/workflow/block-icon' -import { useWorkflow } from '@/app/components/workflow/hooks' +import { + useNodeDataUpdate, + useNodesInteractions, +} from '@/app/components/workflow/hooks' import { canRunBySingle } from '@/app/components/workflow/utils' import { GitBranch01 } from '@/app/components/base/icons/src/vender/line/development' import { Play } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' @@ -36,18 +39,20 @@ const BasePanel: FC = ({ children, }) => { const { t } = useTranslation() + const { handleNodeSelect } = useNodesInteractions() const { - handleNodeSelect, handleNodeDataUpdate, - } = useWorkflow() + handleNodeDataUpdateWithSyncDraft, + } = useNodeDataUpdate() + const handleTitleChange = useCallback((title: string) => { if (!title) return - handleNodeDataUpdate({ id, data: { ...data, title } }) - }, [handleNodeDataUpdate, id, data]) + handleNodeDataUpdateWithSyncDraft({ id, data: { ...data, title } }) + }, [handleNodeDataUpdateWithSyncDraft, id, data]) const handleDescriptionChange = useCallback((desc: string) => { - handleNodeDataUpdate({ id, data: { ...data, desc } }) - }, [handleNodeDataUpdate, id, data]) + handleNodeDataUpdateWithSyncDraft({ id, data: { ...data, desc } }) + }, [handleNodeDataUpdateWithSyncDraft, id, data]) return (
diff --git a/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx b/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx index 2fd1b8adae..4ec98fccc4 100644 --- a/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx +++ b/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx @@ -3,7 +3,7 @@ import type { FC } from 'react' import React, { useCallback } from 'react' import produce from 'immer' import { useTranslation } from 'react-i18next' -import { useWorkflow } from '../../../hooks' +import { useEdgesInteractions } from '../../../hooks' import AddButton from '../../_base/components/add-button' import Item from './class-item' import type { Topic } from '@/app/components/workflow/nodes/question-classifier/types' @@ -22,7 +22,7 @@ const ClassList: FC = ({ onChange, }) => { const { t } = useTranslation() - const { handleEdgeDeleteByDeleteBranch } = useWorkflow() + const { handleEdgeDeleteByDeleteBranch } = useEdgesInteractions() const handleClassChange = useCallback((index: number) => { return (value: Topic) => { diff --git a/web/app/components/workflow/operator/zoom-in-out.tsx b/web/app/components/workflow/operator/zoom-in-out.tsx index dc829cccb8..5e1b9ef9d8 100644 --- a/web/app/components/workflow/operator/zoom-in-out.tsx +++ b/web/app/components/workflow/operator/zoom-in-out.tsx @@ -10,7 +10,7 @@ import { useReactFlow, useViewport, } from 'reactflow' -import { useWorkflow } from '../hooks' +import { useNodesSyncDraft } from '../hooks' import { useStore } from '../store' import { PortalToFollowElem, @@ -29,7 +29,7 @@ const ZoomInOut: FC = () => { fitView, } = useReactFlow() const { zoom } = useViewport() - const { handleSyncWorkflowDraft } = useWorkflow() + const { handleSyncWorkflowDraft } = useNodesSyncDraft() const [open, setOpen] = useState(false) const runningStatus = useStore(s => s.runningStatus) diff --git a/web/app/components/workflow/panel/debug-and-preview/hooks.ts b/web/app/components/workflow/panel/debug-and-preview/hooks.ts index 480a91f164..164b1e9886 100644 --- a/web/app/components/workflow/panel/debug-and-preview/hooks.ts +++ b/web/app/components/workflow/panel/debug-and-preview/hooks.ts @@ -17,7 +17,7 @@ export const useChat = ( ) => { const { t } = useTranslation() const { notify } = useToastContext() - const run = useWorkflowRun() + const { handleRun } = useWorkflowRun() const hasStopResponded = useRef(false) const connversationId = useRef('') const taskIdRef = useRef('') @@ -126,7 +126,7 @@ export const useChat = ( let hasSetResponseId = false - run( + handleRun( params, { onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId, taskId }: any) => { @@ -179,7 +179,7 @@ export const useChat = ( }, }, ) - }, [run, handleResponding, handleUpdateChatList, notify, t, updateCurrentQA]) + }, [handleRun, handleResponding, handleUpdateChatList, notify, t, updateCurrentQA]) return { conversationId: connversationId.current, diff --git a/web/app/components/workflow/panel/inputs-panel.tsx b/web/app/components/workflow/panel/inputs-panel.tsx index 42bc2c69d5..91a717a8e8 100644 --- a/web/app/components/workflow/panel/inputs-panel.tsx +++ b/web/app/components/workflow/panel/inputs-panel.tsx @@ -7,10 +7,7 @@ import { useNodes } from 'reactflow' import FormItem from '../nodes/_base/components/before-run-form/form-item' import { BlockEnum } from '../types' import { useStore } from '../store' -import { - useWorkflow, - useWorkflowRun, -} from '../hooks' +import { useWorkflowRun } from '../hooks' import type { StartNodeType } from '../nodes/start/types' import Button from '@/app/components/base/button' @@ -18,8 +15,10 @@ const InputsPanel = () => { const { t } = useTranslation() const nodes = useNodes() const inputs = useStore(s => s.inputs) - const run = useWorkflowRun() - const { handleRunInit } = useWorkflow() + const { + handleRun, + handleRunSetting, + } = useWorkflowRun() const startNode = nodes.find(node => node.data.type === BlockEnum.Start) const variables = startNode?.data.variables || [] @@ -34,10 +33,10 @@ const InputsPanel = () => { useStore.setState({ showInputsPanel: false }) }, []) - const handleRun = () => { + const doRun = () => { handleCancel() - handleRunInit() - run({ inputs }) + handleRunSetting() + handleRun({ inputs }) } return ( @@ -72,7 +71,7 @@ const InputsPanel = () => {