diff --git a/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx b/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx index 05b37c1469..c3a463c8f9 100644 --- a/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx +++ b/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx @@ -3,7 +3,7 @@ import { useCallback, useMemo, } from 'react' -import { useEdges, useNodes, useStore as useReactflowStore } from 'reactflow' +import { useStore as useReactflowStore } from 'reactflow' import { RiApps2AddLine } from '@remixicon/react' import { useTranslation } from 'react-i18next' import { @@ -11,7 +11,6 @@ import { useWorkflowStore, } from '@/app/components/workflow/store' import { - useChecklist, useChecklistBeforePublish, useNodesReadOnly, useNodesSyncDraft, @@ -19,10 +18,6 @@ import { import Button from '@/app/components/base/button' import AppPublisher from '@/app/components/app/app-publisher' import { useFeatures } from '@/app/components/base/features/hooks' -import type { - CommonEdgeType, - CommonNodeType, -} from '@/app/components/workflow/types' import { BlockEnum, InputVarType, @@ -97,18 +92,9 @@ const FeaturesTrigger = () => { } }, [appID, setAppDetail]) const { mutateAsync: publishWorkflow } = usePublishWorkflow() - const nodes = useNodes() - const edges = useEdges() - const needWarningNodes = useChecklist(nodes, edges) const updatePublishedWorkflow = useInvalidateAppWorkflow() const onPublish = useCallback(async (params?: PublishWorkflowParams) => { - // First check if there are any items in the checklist - if (needWarningNodes.length > 0) { - notify({ type: 'error', message: t('workflow.panel.checklistTip') }) - throw new Error('Checklist has unresolved items') - } - // Then perform the detailed validation if (await handleCheckBeforePublish()) { const res = await publishWorkflow({ @@ -128,7 +114,7 @@ const FeaturesTrigger = () => { else { throw new Error('Checklist failed') } - }, [needWarningNodes, handleCheckBeforePublish, publishWorkflow, notify, appID, t, updatePublishedWorkflow, updateAppDetail, workflowStore, resetWorkflowVersionHistory]) + }, [handleCheckBeforePublish, publishWorkflow, notify, appID, t, updatePublishedWorkflow, updateAppDetail, workflowStore, resetWorkflowVersionHistory]) const onPublisherToggle = useCallback((state: boolean) => { if (state) diff --git a/web/app/components/workflow/features.tsx b/web/app/components/workflow/features.tsx index b54ffdf167..e1960cb060 100644 --- a/web/app/components/workflow/features.tsx +++ b/web/app/components/workflow/features.tsx @@ -2,27 +2,25 @@ import { memo, useCallback, } from 'react' -import { useNodes } from 'reactflow' import { useStore } from './store' import { useIsChatMode, useNodesReadOnly, useNodesSyncDraft, } from './hooks' -import { type CommonNodeType, type InputVar, InputVarType, type Node } from './types' +import { type InputVar, InputVarType, type Node } from './types' import useConfig from './nodes/start/use-config' import type { StartNodeType } from './nodes/start/types' import type { PromptVariable } from '@/models/debug' import NewFeaturePanel from '@/app/components/base/features/new-feature-panel' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' const Features = () => { const setShowFeaturesPanel = useStore(s => s.setShowFeaturesPanel) const isChatMode = useIsChatMode() const { nodesReadOnly } = useNodesReadOnly() const { handleSyncWorkflowDraft } = useNodesSyncDraft() - const nodes = useNodes() - - const startNode = nodes.find(node => node.data.type === 'start') + const startNode = useFindNode(['sys']) const { id, data } = startNode as Node const { handleAddVariable } = useConfig(id, data) diff --git a/web/app/components/workflow/header/header-in-normal.tsx b/web/app/components/workflow/header/header-in-normal.tsx index 1c3a442422..7ee6320a4b 100644 --- a/web/app/components/workflow/header/header-in-normal.tsx +++ b/web/app/components/workflow/header/header-in-normal.tsx @@ -1,12 +1,11 @@ import { useCallback, } from 'react' -import { useNodes } from 'reactflow' +import { useStore as useReactFlowStore } from 'reactflow' import { useStore, useWorkflowStore, } from '../store' -import type { StartNodeType } from '../nodes/start/types' import { useNodesInteractions, useNodesReadOnly, @@ -39,8 +38,7 @@ const HeaderInNormal = ({ const setShowDebugAndPreviewPanel = useStore(s => s.setShowDebugAndPreviewPanel) const setShowVariableInspectPanel = useStore(s => s.setShowVariableInspectPanel) const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel) - const nodes = useNodes() - const selectedNode = nodes.find(node => node.data.selected) + const selectedNode = useReactFlowStore(s => s.getNodes().find(node => node.data.selected)) const { handleBackupDraft } = useWorkflowRun() const { closeAllInputFieldPanels } = useInputFieldPanel() diff --git a/web/app/components/workflow/hooks/use-find-node.ts b/web/app/components/workflow/hooks/use-find-node.ts new file mode 100644 index 0000000000..f4da759469 --- /dev/null +++ b/web/app/components/workflow/hooks/use-find-node.ts @@ -0,0 +1,16 @@ +import { useStore } from 'reactflow' +import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' +import { BlockEnum } from '@/app/components/workflow/types' +import type { Node, ValueSelector } from '@/app/components/workflow/types' + +export const useFindNode = (valueSelector: ValueSelector = [], nodes: Node[] = []) => { + const nodeFromOuterNodes = nodes.find(node => node.id === valueSelector[0]) + const node = useStore((s) => { + const nodes = s.getNodes() + if (isSystemVar(valueSelector)) + return nodes.find(node => node.data.type === BlockEnum.Start) + return nodes.find(node => node.id === valueSelector[0]) + }) + + return nodeFromOuterNodes || node +} diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 75c4d51390..579b3b6d62 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -61,7 +61,6 @@ import { CUSTOM_SIMPLE_NODE } from './simple-node/constants' import CustomDataSourceEmptyNode from './nodes/data-source-empty' import { CUSTOM_DATA_SOURCE_EMPTY_NODE } from './nodes/data-source-empty/constants' import Operator from './operator' -import { useWorkflowSearch } from './hooks/use-workflow-search' import Control from './operator/control' import CustomEdge from './custom-edge' import CustomConnectionLine from './custom-connection-line' @@ -290,7 +289,7 @@ export const Workflow: FC = memo(({ useShortcuts() // Initialize workflow node search functionality - useWorkflowSearch() + // useWorkflowSearch() // Set up scroll to node event listener using the utility function useEffect(() => { diff --git a/web/app/components/workflow/node-contextmenu.tsx b/web/app/components/workflow/node-contextmenu.tsx index 311bf1fddf..7032b0488e 100644 --- a/web/app/components/workflow/node-contextmenu.tsx +++ b/web/app/components/workflow/node-contextmenu.tsx @@ -4,18 +4,16 @@ import { useRef, } from 'react' import { useClickAway } from 'ahooks' -import { useNodes } from 'reactflow' import PanelOperatorPopup from './nodes/_base/components/panel-operator/panel-operator-popup' -import type { Node } from './types' import { useStore } from './store' import { usePanelInteractions } from './hooks' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' const NodeContextmenu = () => { const ref = useRef(null) - const nodes = useNodes() const { handleNodeContextmenuCancel, handlePaneContextmenuCancel } = usePanelInteractions() const nodeMenu = useStore(s => s.nodeMenu) - const currentNode = nodes.find(node => node.id === nodeMenu?.nodeId) as Node + const currentNode = useFindNode(nodeMenu?.nodeId ? [nodeMenu.nodeId] : []) useEffect(() => { if (nodeMenu) diff --git a/web/app/components/workflow/nodes/_base/components/variable-tag.tsx b/web/app/components/workflow/nodes/_base/components/variable-tag.tsx index 4d3dfe217c..d10e3abc53 100644 --- a/web/app/components/workflow/nodes/_base/components/variable-tag.tsx +++ b/web/app/components/workflow/nodes/_base/components/variable-tag.tsx @@ -1,18 +1,18 @@ import { useCallback, useMemo } from 'react' -import { useNodes, useReactFlow, useStoreApi } from 'reactflow' +import { useReactFlow, useStoreApi } from 'reactflow' import { useTranslation } from 'react-i18next' import type { - CommonNodeType, Node, ValueSelector, VarType, } from '@/app/components/workflow/types' import { BlockEnum } from '@/app/components/workflow/types' -import { getNodeInfoById, isConversationVar, isENV, isRagVariableVar, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' +import { isConversationVar, isENV, isRagVariableVar, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' import { isExceptionVariable } from '@/app/components/workflow/utils' import { VariableLabelInSelect, } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' type VariableTagProps = { valueSelector: ValueSelector @@ -26,16 +26,16 @@ const VariableTag = ({ isShort, availableNodes, }: VariableTagProps) => { - const nodes = useNodes() const isRagVar = isRagVariableVar(valueSelector) + const nodeFromAvailableNodes = useFindNode(isRagVar ? [valueSelector[1]] : [valueSelector[0]], availableNodes) const node = useMemo(() => { if (isSystemVar(valueSelector)) { const startNode = availableNodes?.find(n => n.data.type === BlockEnum.Start) if (startNode) return startNode } - return getNodeInfoById(availableNodes || nodes, isRagVar ? valueSelector[1] : valueSelector[0]) - }, [nodes, valueSelector, availableNodes, isRagVar]) + return nodeFromAvailableNodes + }, [valueSelector, availableNodes, isRagVar, nodeFromAvailableNodes]) as Node const isEnv = isENV(valueSelector) const isChatVar = isConversationVar(valueSelector) diff --git a/web/app/components/workflow/nodes/assigner/components/operation-item.tsx b/web/app/components/workflow/nodes/assigner/components/operation-item.tsx new file mode 100644 index 0000000000..816620d565 --- /dev/null +++ b/web/app/components/workflow/nodes/assigner/components/operation-item.tsx @@ -0,0 +1,35 @@ +import { memo } from 'react' +import { useTranslation } from 'react-i18next' +import type { AssignerNodeOperation } from '../types' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' +import { + VariableLabelInNode, +} from '@/app/components/workflow/nodes/_base/components/variable/variable-label' +import Badge from '@/app/components/base/badge' + +type OperationItemProps = { + value: AssignerNodeOperation +} + +const i18nPrefix = 'workflow.nodes.assigner' + +const OperationItem = ({ value }: OperationItemProps) => { + const { t } = useTranslation() + const variable = value.variable_selector + const node = useFindNode(variable) + if (!variable || variable.length === 0) + return null + + return ( + + } + /> + ) +} + +export default memo(OperationItem) diff --git a/web/app/components/workflow/nodes/assigner/hooks.ts b/web/app/components/workflow/nodes/assigner/hooks.ts index d0600e5e09..9b1f1abbf5 100644 --- a/web/app/components/workflow/nodes/assigner/hooks.ts +++ b/web/app/components/workflow/nodes/assigner/hooks.ts @@ -1,6 +1,6 @@ import { useCallback } from 'react' import { - useNodes, + useStoreApi, } from 'reactflow' import { uniqBy } from 'lodash-es' import { @@ -15,12 +15,14 @@ import type { import { AssignerNodeInputType, WriteMode } from './types' export const useGetAvailableVars = () => { - const nodes: Node[] = useNodes() + const store = useStoreApi() const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow() const { getNodeAvailableVars } = useWorkflowVariables() const isChatMode = useIsChatMode() const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => { const availableNodes: Node[] = [] + const { getNodes } = store.getState() + const nodes = getNodes() const currentNode = nodes.find(node => node.id === nodeId)! if (!currentNode) @@ -52,7 +54,7 @@ export const useGetAvailableVars = () => { isChatMode, filterVar, }) - }, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode]) + }, [store, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode]) return getAvailableVars } diff --git a/web/app/components/workflow/nodes/assigner/node.tsx b/web/app/components/workflow/nodes/assigner/node.tsx index 5e5950d715..6ed44aa730 100644 --- a/web/app/components/workflow/nodes/assigner/node.tsx +++ b/web/app/components/workflow/nodes/assigner/node.tsx @@ -1,14 +1,14 @@ import type { FC } from 'react' import React from 'react' -import { useNodes } from 'reactflow' import { useTranslation } from 'react-i18next' import type { AssignerNodeType } from './types' -import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' -import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' +import type { NodeProps } from '@/app/components/workflow/types' import { VariableLabelInNode, } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' import Badge from '@/app/components/base/badge' +import OperationItem from './components/operation-item' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' const i18nPrefix = 'workflow.nodes.assigner' @@ -16,7 +16,7 @@ const NodeComponent: FC> = ({ data, }) => { const { t } = useTranslation() - const nodes: Node[] = useNodes() + const node = useFindNode((data as any).assigned_variable_selector) if (data.version === '2') { const { items: operationItems } = data const validOperationItems = operationItems?.filter(item => @@ -37,22 +37,7 @@ const NodeComponent: FC> = ({ return (
{operationItems.map((value, index) => { - const variable = value.variable_selector - if (!variable || variable.length === 0) - return null - const isSystem = isSystemVar(variable) - const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) - return ( - - } - /> - ) + return })}
) @@ -62,8 +47,6 @@ const NodeComponent: FC> = ({ if (!variable || variable.length === 0) return null - const isSystem = isSystemVar(variable) - const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) return (
diff --git a/web/app/components/workflow/nodes/document-extractor/node.tsx b/web/app/components/workflow/nodes/document-extractor/node.tsx index ab7fe9a9a6..8e64641046 100644 --- a/web/app/components/workflow/nodes/document-extractor/node.tsx +++ b/web/app/components/workflow/nodes/document-extractor/node.tsx @@ -1,13 +1,12 @@ import type { FC } from 'react' import React from 'react' -import { useNodes } from 'reactflow' import { useTranslation } from 'react-i18next' import type { DocExtractorNodeType } from './types' -import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' -import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' +import type { NodeProps } from '@/app/components/workflow/types' import { VariableLabelInNode, } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' const i18nPrefix = 'workflow.nodes.docExtractor' @@ -15,15 +14,12 @@ const NodeComponent: FC> = ({ data, }) => { const { t } = useTranslation() - - const nodes: Node[] = useNodes() const { variable_selector: variable } = data + const node = useFindNode(variable) if (!variable || variable.length === 0) return null - const isSystem = isSystemVar(variable) - const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) return (
{t(`${i18nPrefix}.inputVar`)}
diff --git a/web/app/components/workflow/nodes/if-else/components/condition-value.tsx b/web/app/components/workflow/nodes/if-else/components/condition-value.tsx index 8fe5578819..86c8ba4d00 100644 --- a/web/app/components/workflow/nodes/if-else/components/condition-value.tsx +++ b/web/app/components/workflow/nodes/if-else/components/condition-value.tsx @@ -3,7 +3,6 @@ import { useMemo, } from 'react' import { useTranslation } from 'react-i18next' -import { useNodes } from 'reactflow' import { ComparisonOperator } from '../types' import { comparisonOperatorNotRequireValue, @@ -12,13 +11,10 @@ import { import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from '../../constants' import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' import { isExceptionVariable } from '@/app/components/workflow/utils' -import type { - CommonNodeType, - Node, -} from '@/app/components/workflow/types' import { VariableLabelInText, } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' type ConditionValueProps = { variableSelector: string[] @@ -33,11 +29,10 @@ const ConditionValue = ({ value, }: ConditionValueProps) => { const { t } = useTranslation() - const nodes = useNodes() + const node = useFindNode(variableSelector) const variableName = labelName || (isSystemVar(variableSelector) ? variableSelector.slice(0).join('.') : variableSelector.slice(1).join('.')) const operatorName = isComparisonOperatorNeedTranslate(operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${operator}`) : operator const notHasValue = comparisonOperatorNotRequireValue(operator) - const node: Node | undefined = nodes.find(n => n.id === variableSelector[0]) as Node const isException = isExceptionVariable(variableName, node?.data.type) const formatValue = useMemo(() => { if (notHasValue) diff --git a/web/app/components/workflow/nodes/list-operator/node.tsx b/web/app/components/workflow/nodes/list-operator/node.tsx index 3c59f36587..bb2c04d9fb 100644 --- a/web/app/components/workflow/nodes/list-operator/node.tsx +++ b/web/app/components/workflow/nodes/list-operator/node.tsx @@ -1,13 +1,12 @@ import type { FC } from 'react' import React from 'react' -import { useNodes } from 'reactflow' import { useTranslation } from 'react-i18next' import type { ListFilterNodeType } from './types' -import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' -import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' +import type { NodeProps } from '@/app/components/workflow/types' import { VariableLabelInNode, } from '@/app/components/workflow/nodes/_base/components/variable/variable-label' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' const i18nPrefix = 'workflow.nodes.listFilter' @@ -15,15 +14,12 @@ const NodeComponent: FC> = ({ data, }) => { const { t } = useTranslation() - - const nodes: Node[] = useNodes() const { variable } = data + const node = useFindNode(variable) if (!variable || variable.length === 0) return null - const isSystem = isSystemVar(variable) - const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) return (
{t(`${i18nPrefix}.inputVar`)}
diff --git a/web/app/components/workflow/nodes/variable-assigner/components/node-group-item.tsx b/web/app/components/workflow/nodes/variable-assigner/components/node-group-item.tsx index e96475b953..d0dfdddb34 100644 --- a/web/app/components/workflow/nodes/variable-assigner/components/node-group-item.tsx +++ b/web/app/components/workflow/nodes/variable-assigner/components/node-group-item.tsx @@ -3,11 +3,8 @@ import { useMemo, } from 'react' import { useTranslation } from 'react-i18next' -import { useNodes } from 'reactflow' import { useStore } from '../../../store' -import { BlockEnum } from '../../../types' import type { - Node, ValueSelector, VarType, } from '../../../types' @@ -18,12 +15,8 @@ import { } from '../hooks' import { filterVar } from '../utils' import AddVariable from './add-variable' -import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' import cn from '@/utils/classnames' -import { isExceptionVariable } from '@/app/components/workflow/utils' -import { - VariableLabelInNode, -} from '@/app/components/workflow/nodes/_base/components/variable/variable-label' +import VariableLabelItem from './variable-label-item' const i18nPrefix = 'workflow.nodes.variableAssigner' type GroupItem = { @@ -44,7 +37,6 @@ const NodeGroupItem = ({ const { t } = useTranslation() const enteringNodePayload = useStore(s => s.enteringNodePayload) const hoveringAssignVariableGroupId = useStore(s => s.hoveringAssignVariableGroupId) - const nodes: Node[] = useNodes() const { handleGroupItemMouseEnter, handleGroupItemMouseLeave, @@ -128,21 +120,7 @@ const NodeGroupItem = ({
{ item.variables.map((variable = [], index) => { - const isSystem = isSystemVar(variable) - - const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0]) - const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.') - const isException = isExceptionVariable(varName, node?.data.type) - - return ( - - ) + return }) }
diff --git a/web/app/components/workflow/nodes/variable-assigner/components/variable-label-item.tsx b/web/app/components/workflow/nodes/variable-assigner/components/variable-label-item.tsx new file mode 100644 index 0000000000..17bfab3333 --- /dev/null +++ b/web/app/components/workflow/nodes/variable-assigner/components/variable-label-item.tsx @@ -0,0 +1,29 @@ +import { memo } from 'react' +import type { ValueSelector } from '@/app/components/workflow/types' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' +import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' +import { isExceptionVariable } from '@/app/components/workflow/utils' +import { + VariableLabelInNode, +} from '@/app/components/workflow/nodes/_base/components/variable/variable-label' + +type VariableLabelItemProps = { + variable: ValueSelector +} +const VariableLabelItem = ({ variable }: VariableLabelItemProps) => { + const isSystem = isSystemVar(variable) + const node = useFindNode(variable) + const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.') + const isException = isExceptionVariable(varName, node?.data.type) + + return ( + + ) +} + +export default memo(VariableLabelItem) diff --git a/web/app/components/workflow/nodes/variable-assigner/hooks.ts b/web/app/components/workflow/nodes/variable-assigner/hooks.ts index d4e4115a78..0243d0a2aa 100644 --- a/web/app/components/workflow/nodes/variable-assigner/hooks.ts +++ b/web/app/components/workflow/nodes/variable-assigner/hooks.ts @@ -1,6 +1,5 @@ import { useCallback } from 'react' import { - useNodes, useStoreApi, } from 'reactflow' import { uniqBy } from 'lodash-es' @@ -122,12 +121,14 @@ export const useVariableAssigner = () => { } export const useGetAvailableVars = () => { - const nodes: Node[] = useNodes() + const store = useStoreApi() const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow() const { getNodeAvailableVars } = useWorkflowVariables() const isChatMode = useIsChatMode() const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => { const availableNodes: Node[] = [] + const { getNodes } = store.getState() + const nodes = getNodes() const currentNode = nodes.find(node => node.id === nodeId)! if (!currentNode) @@ -158,7 +159,7 @@ export const useGetAvailableVars = () => { isChatMode, filterVar, }) - }, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode]) + }, [store, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode]) return getAvailableVars } diff --git a/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx b/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx index 1a97357da5..d8cbded193 100644 --- a/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx +++ b/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx @@ -1,6 +1,5 @@ import { memo, useCallback, useEffect, useImperativeHandle, useMemo } from 'react' -import { useNodes } from 'reactflow' -import { BlockEnum } from '../../types' +import type { Node } from '../../types' import { useStore, useWorkflowStore, @@ -23,6 +22,7 @@ import { getLastAnswer, isValidGeneratedAnswer } from '@/app/components/base/cha import type { FileEntity } from '@/app/components/base/file-uploader/types' import { useEventEmitterContextContext } from '@/context/event-emitter' import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' type ChatWrapperProps = { showConversationVariableModal: boolean @@ -42,8 +42,7 @@ const ChatWrapper = ( ref: React.RefObject; }, ) => { - const nodes = useNodes() - const startNode = nodes.find(node => node.data.type === BlockEnum.Start) + const startNode = useFindNode(['sys']) as Node const startVariables = startNode?.data.variables const appDetail = useAppStore(s => s.appDetail) const workflowStore = useWorkflowStore() diff --git a/web/app/components/workflow/panel/debug-and-preview/index.tsx b/web/app/components/workflow/panel/debug-and-preview/index.tsx index baf4c21dcd..9af2ad5567 100644 --- a/web/app/components/workflow/panel/debug-and-preview/index.tsx +++ b/web/app/components/workflow/panel/debug-and-preview/index.tsx @@ -8,13 +8,13 @@ import { import { RiCloseLine, RiEqualizer2Line } from '@remixicon/react' import { useTranslation } from 'react-i18next' -import { useNodes } from 'reactflow' +import { useStore as useReactFlowStore } from 'reactflow' import { useWorkflowInteractions, } from '../../hooks' import { useEdgesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-edges-interactions-without-sync' import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync' -import { BlockEnum } from '../../types' +import type { Node } from '../../types' import type { StartNodeType } from '../../nodes/start/types' import { useResizePanel } from '../../nodes/_base/hooks/use-resize-panel' import ChatWrapper from './chat-wrapper' @@ -24,6 +24,7 @@ import Tooltip from '@/app/components/base/tooltip' import ActionButton, { ActionButtonState } from '@/app/components/base/action-button' import { useStore } from '@/app/components/workflow/store' import { debounce, noop } from 'lodash-es' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' export type ChatWrapperRefType = { handleRestart: () => void @@ -35,9 +36,8 @@ const DebugAndPreview = () => { const { handleNodeCancelRunningStatus } = useNodesInteractionsWithoutSync() const { handleEdgeCancelRunningStatus } = useEdgesInteractionsWithoutSync() const [expanded, setExpanded] = useState(true) - const nodes = useNodes() - const selectedNode = nodes.find(node => node.data.selected) - const startNode = nodes.find(node => node.data.type === BlockEnum.Start) + const startNode = useFindNode(['sys']) as Node + const selectedNode = useReactFlowStore(s => s.getNodes().find(node => node.data.selected)) const variables = startNode?.data.variables || [] const visibleVariables = variables.filter(v => v.hide !== true) diff --git a/web/app/components/workflow/panel/debug-and-preview/user-input.tsx b/web/app/components/workflow/panel/debug-and-preview/user-input.tsx index 0670d9a52b..4ce8f9707f 100644 --- a/web/app/components/workflow/panel/debug-and-preview/user-input.tsx +++ b/web/app/components/workflow/panel/debug-and-preview/user-input.tsx @@ -1,21 +1,20 @@ import { memo, } from 'react' -import { useNodes } from 'reactflow' import FormItem from '../../nodes/_base/components/before-run-form/form-item' -import { BlockEnum } from '../../types' +import type { Node } from '../../types' import { useStore, useWorkflowStore, } from '../../store' import type { StartNodeType } from '../../nodes/start/types' import cn from '@/utils/classnames' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' const UserInput = () => { const workflowStore = useWorkflowStore() const inputs = useStore(s => s.inputs) - const nodes = useNodes() - const startNode = nodes.find(node => node.data.type === BlockEnum.Start) + const startNode = useFindNode(['sys']) as Node const variables = startNode?.data.variables || [] const visibleVariables = variables.filter(v => v.hide !== true) diff --git a/web/app/components/workflow/panel/inputs-panel.tsx b/web/app/components/workflow/panel/inputs-panel.tsx index 11492539df..8898fc4347 100644 --- a/web/app/components/workflow/panel/inputs-panel.tsx +++ b/web/app/components/workflow/panel/inputs-panel.tsx @@ -4,10 +4,8 @@ import { useMemo, } from 'react' import { useTranslation } from 'react-i18next' -import { useNodes } from 'reactflow' import FormItem from '../nodes/_base/components/before-run-form/form-item' import { - BlockEnum, InputVarType, WorkflowRunningStatus, } from '../types' @@ -16,7 +14,6 @@ import { useWorkflowStore, } from '../store' import { useWorkflowRun } from '../hooks' -import type { StartNodeType } from '../nodes/start/types' import { TransferMethod } from '../../base/text-generation/types' import Button from '@/app/components/base/button' import { @@ -24,6 +21,7 @@ import { } from '@/app/components/base/chat/chat/utils' import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks' import { useHooksStore } from '../hooks-store' +import { useFindNode } from '@/app/components/workflow/hooks/use-find-node' type Props = { onRun: () => void @@ -37,19 +35,18 @@ const InputsPanel = ({ onRun }: Props) => { setInputs: s.setInputs, })) const fileSettings = useHooksStore(s => s.configsMap?.fileSettings) - const nodes = useNodes() + const startNode = useFindNode(['sys']) const files = useStore(s => s.files) const workflowRunningData = useStore(s => s.workflowRunningData) const { handleRun, } = useWorkflowRun() - const startNode = nodes.find(node => node.data.type === BlockEnum.Start) const startVariables = startNode?.data.variables const { checkInputsForm } = useCheckInputsForms() const initialInputs = { ...inputs } if (startVariables) { - startVariables.forEach((variable) => { + startVariables.forEach((variable: any) => { if (variable.default) initialInputs[variable.variable] = variable.default if (inputs[variable.variable] !== undefined) @@ -110,7 +107,7 @@ const InputsPanel = ({ onRun }: Props) => { <>
{ - variables.map((variable, index) => ( + variables.map((variable: any, index: number) => (
{ getNodesReadOnly, } = useNodesReadOnly() const workflowRunningData = useStore(s => s.workflowRunningData) - const nodes = useNodes() - const isStepRunning = useMemo(() => nodes.some(node => node.data._singleRunningStatus === NodeRunningStatus.Running), [nodes]) + const isStepRunning = useReactFlowStore(s => s.getNodes().some(node => node.data._singleRunningStatus === NodeRunningStatus.Running)) const isPreviewRunning = useMemo(() => { if (!workflowRunningData) return false