diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/workflow/page.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/workflow/page.tsx
index 467d5be3c0..2b9573e1dd 100644
--- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/workflow/page.tsx
+++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/workflow/page.tsx
@@ -2,52 +2,13 @@
import { memo } from 'react'
import Workflow from '@/app/components/workflow'
-
-// export function createNodesAndEdges(xNodes = 10, yNodes = 10) {
-// const nodes = []
-// const edges = []
-// let nodeId = 1
-// let recentNodeId = null
-
-// for (let y = 0; y < yNodes; y++) {
-// for (let x = 0; x < xNodes; x++) {
-// const position = { x: x * 200, y: y * 50 }
-// const node = {
-// id: `stress-${nodeId.toString()}`,
-// type: 'custom',
-// data: { type: 'start', title: '开始', variables: [] },
-// position,
-// }
-// nodes.push(node)
-
-// if (recentNodeId && nodeId <= xNodes * yNodes) {
-// edges.push({
-// id: `${x}-${y}`,
-// type: 'custom',
-// source: `stress-${recentNodeId.toString()}`,
-// target: `stress-${nodeId.toString()}`,
-// })
-// }
-
-// recentNodeId = nodeId
-// nodeId++
-// }
-// }
-
-// return { nodes, edges }
-// }
+import { useStore } from '@/app/components/app/store'
const Page = () => {
- // const {
- // nodes,
- // edges,
- // } = createNodesAndEdges()
+ const appDetail = useStore(s => s.appDetail)!
return (
-
-
+
+
)
}
diff --git a/web/app/components/workflow/context.tsx b/web/app/components/workflow/context.tsx
new file mode 100644
index 0000000000..77c8291389
--- /dev/null
+++ b/web/app/components/workflow/context.tsx
@@ -0,0 +1,24 @@
+import {
+ createContext,
+ useRef,
+} from 'react'
+import { createWorkflowStore } from './store'
+
+type WorkflowStore = ReturnType
+export const WorkflowContext = createContext(null)
+
+type WorkflowProviderProps = {
+ children: React.ReactNode
+}
+export const WorkflowContextProvider = ({ children }: WorkflowProviderProps) => {
+ const storeRef = useRef()
+
+ if (!storeRef.current)
+ storeRef.current = createWorkflowStore()
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/web/app/components/workflow/header/index.tsx b/web/app/components/workflow/header/index.tsx
index 9ad43692be..84abc4a6ad 100644
--- a/web/app/components/workflow/header/index.tsx
+++ b/web/app/components/workflow/header/index.tsx
@@ -4,7 +4,10 @@ import {
useCallback,
} from 'react'
import { useTranslation } from 'react-i18next'
-import { useStore } from '../store'
+import {
+ useStore,
+ useWorkflowStore,
+} from '../store'
import {
useIsChatMode,
useWorkflowRun,
@@ -20,6 +23,7 @@ import { useStore as useAppStore } from '@/app/components/app/store'
const Header: FC = () => {
const { t } = useTranslation()
+ const workflowStore = useWorkflowStore()
const appDetail = useAppStore(s => s.appDetail)
const appSidebarExpand = useAppStore(s => s.appSidebarExpand)
const isChatMode = useIsChatMode()
@@ -30,8 +34,8 @@ const Header: FC = () => {
if (runningStatus)
return
- useStore.setState({ showFeaturesPanel: true })
- }, [runningStatus])
+ workflowStore.setState({ showFeaturesPanel: true })
+ }, [runningStatus, workflowStore])
const handleGoBackToEdit = useCallback(() => {
handleRunSetting(true)
diff --git a/web/app/components/workflow/header/run-and-history.tsx b/web/app/components/workflow/header/run-and-history.tsx
index 299d20cc87..73036e5fe1 100644
--- a/web/app/components/workflow/header/run-and-history.tsx
+++ b/web/app/components/workflow/header/run-and-history.tsx
@@ -1,7 +1,10 @@
import type { FC } from 'react'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
-import { useStore } from '../store'
+import {
+ useStore,
+ useWorkflowStore,
+} from '../store'
import {
useIsChatMode,
useWorkflowRun,
@@ -14,12 +17,13 @@ import { Loading02 } from '@/app/components/base/icons/src/vender/line/general'
const RunMode = memo(() => {
const { t } = useTranslation()
+ const workflowStore = useWorkflowStore()
const runningStatus = useStore(s => s.runningStatus)
const showInputsPanel = useStore(s => s.showInputsPanel)
const isRunning = runningStatus === WorkflowRunningStatus.Running
const handleClick = () => {
- useStore.setState({ showInputsPanel: true })
+ workflowStore.setState({ showInputsPanel: true })
}
return (
@@ -91,6 +95,7 @@ PreviewMode.displayName = 'PreviewMode'
const RunAndHistory: FC = () => {
const { t } = useTranslation()
+ const workflowStore = useWorkflowStore()
const isChatMode = useIsChatMode()
const showRunHistory = useStore(state => state.showRunHistory)
@@ -111,7 +116,7 @@ const RunAndHistory: FC = () => {
flex items-center justify-center w-7 h-7 rounded-md hover:bg-black/5 cursor-pointer
${showRunHistory && 'bg-primary-50'}
`}
- onClick={() => useStore.setState({ showRunHistory: true })}
+ onClick={() => workflowStore.setState({ showRunHistory: true })}
>
diff --git a/web/app/components/workflow/hooks/use-edges-interactions.ts b/web/app/components/workflow/hooks/use-edges-interactions.ts
index b4f3afd8ad..01b96a3c42 100644
--- a/web/app/components/workflow/hooks/use-edges-interactions.ts
+++ b/web/app/components/workflow/hooks/use-edges-interactions.ts
@@ -8,7 +8,7 @@ import {
getConnectedEdges,
useStoreApi,
} from 'reactflow'
-import { useStore } from '../store'
+import { useWorkflowStore } from '../store'
import type {
Edge,
Node,
@@ -18,10 +18,11 @@ import { useNodesSyncDraft } from './use-nodes-sync-draft'
export const useEdgesInteractions = () => {
const store = useStoreApi()
+ const workflowStore = useWorkflowStore()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const handleEdgeEnter = useCallback((_, edge) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -36,10 +37,10 @@ export const useEdgesInteractions = () => {
currentEdge.data = { ...currentEdge.data, _hovering: true }
})
setEdges(newEdges)
- }, [store])
+ }, [store, workflowStore])
const handleEdgeLeave = useCallback((_, edge) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -54,10 +55,10 @@ export const useEdgesInteractions = () => {
currentEdge.data = { ...currentEdge.data, _hovering: false }
})
setEdges(newEdges)
- }, [store])
+ }, [store, workflowStore])
const handleEdgeDeleteByDeleteBranch = useCallback((nodeId: string, branchId: string) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -90,10 +91,10 @@ export const useEdgesInteractions = () => {
})
setEdges(newEdges)
handleSyncWorkflowDraft()
- }, [store, handleSyncWorkflowDraft])
+ }, [store, handleSyncWorkflowDraft, workflowStore])
const handleEdgeDelete = useCallback(() => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -125,10 +126,10 @@ export const useEdgesInteractions = () => {
})
setEdges(newEdges)
handleSyncWorkflowDraft()
- }, [store, handleSyncWorkflowDraft])
+ }, [store, workflowStore, handleSyncWorkflowDraft])
const handleEdgesChange = useCallback((changes) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -145,7 +146,7 @@ export const useEdgesInteractions = () => {
})
})
setEdges(newEdges)
- }, [store])
+ }, [store, workflowStore])
const handleVariableAssignerEdgesChange = useCallback((nodeId: string, variables: any) => {
const {
diff --git a/web/app/components/workflow/hooks/use-node-data-update.ts b/web/app/components/workflow/hooks/use-node-data-update.ts
index 3f8175683c..d46fbb4c47 100644
--- a/web/app/components/workflow/hooks/use-node-data-update.ts
+++ b/web/app/components/workflow/hooks/use-node-data-update.ts
@@ -1,7 +1,7 @@
import { useCallback } from 'react'
import produce from 'immer'
import { useStoreApi } from 'reactflow'
-import { useStore } from '../store'
+import { useWorkflowStore } from '../store'
import { useNodesSyncDraft } from './use-nodes-sync-draft'
type NodeDataUpdatePayload = {
@@ -11,6 +11,7 @@ type NodeDataUpdatePayload = {
export const useNodeDataUpdate = () => {
const store = useStoreApi()
+ const workflowStore = useWorkflowStore()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const handleNodeDataUpdate = useCallback(({ id, data }: NodeDataUpdatePayload) => {
@@ -27,14 +28,14 @@ export const useNodeDataUpdate = () => {
}, [store])
const handleNodeDataUpdateWithSyncDraft = useCallback((payload: NodeDataUpdatePayload) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
handleNodeDataUpdate(payload)
handleSyncWorkflowDraft(true)
- }, [handleSyncWorkflowDraft, handleNodeDataUpdate])
+ }, [handleSyncWorkflowDraft, handleNodeDataUpdate, workflowStore])
return {
handleNodeDataUpdate,
diff --git a/web/app/components/workflow/hooks/use-nodes-interactions.ts b/web/app/components/workflow/hooks/use-nodes-interactions.ts
index d9bfff1110..a5c7f00da7 100644
--- a/web/app/components/workflow/hooks/use-nodes-interactions.ts
+++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts
@@ -18,7 +18,7 @@ import type {
OnNodeAdd,
} from '../types'
import { BlockEnum } from '../types'
-import { useStore } from '../store'
+import { useWorkflowStore } from '../store'
import {
NODE_WIDTH_X_OFFSET,
Y_OFFSET,
@@ -36,6 +36,7 @@ import { useWorkflow } from './use-workflow'
export const useNodesInteractions = () => {
const store = useStoreApi()
+ const workflowStore = useWorkflowStore()
const nodesInitialData = useNodesInitialData()
const nodesExtraData = useNodesExtraData()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
@@ -46,16 +47,16 @@ export const useNodesInteractions = () => {
const handleNodeDragStart = useCallback((_, node) => {
const {
runningStatus,
- } = useStore.getState()
+ } = workflowStore.getState()
if (runningStatus)
return
dragNodeStartPosition.current = { x: node.position.x, y: node.position.y }
- }, [])
+ }, [workflowStore])
const handleNodeDrag = useCallback((e, node: Node) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -67,7 +68,7 @@ export const useNodesInteractions = () => {
const {
setHelpLineHorizontal,
setHelpLineVertical,
- } = useStore.getState()
+ } = workflowStore.getState()
e.stopPropagation()
const nodes = getNodes()
@@ -157,14 +158,14 @@ export const useNodesInteractions = () => {
})
setNodes(newNodes)
- }, [store])
+ }, [store, workflowStore])
const handleNodeDragStop = useCallback((_, node) => {
const {
runningStatus,
setHelpLineHorizontal,
setHelpLineVertical,
- } = useStore.getState()
+ } = workflowStore.getState()
if (runningStatus)
return
@@ -175,10 +176,10 @@ export const useNodesInteractions = () => {
setHelpLineVertical()
handleSyncWorkflowDraft()
}
- }, [handleSyncWorkflowDraft])
+ }, [handleSyncWorkflowDraft, workflowStore])
const handleNodeEnter = useCallback((_, node) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -215,10 +216,10 @@ export const useNodesInteractions = () => {
})
})
setEdges(newEdges)
- }, [store, nodesExtraData])
+ }, [store, nodesExtraData, workflowStore])
const handleNodeLeave = useCallback(() => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -241,10 +242,10 @@ export const useNodesInteractions = () => {
})
})
setEdges(newEdges)
- }, [store])
+ }, [store, workflowStore])
const handleNodeSelect = useCallback((nodeId: string, cancelSelection?: boolean) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -270,18 +271,18 @@ export const useNodesInteractions = () => {
})
setNodes(newNodes)
handleSyncWorkflowDraft()
- }, [store, handleSyncWorkflowDraft])
+ }, [store, handleSyncWorkflowDraft, workflowStore])
const handleNodeClick = useCallback((_, node) => {
const {
runningStatus,
- } = useStore.getState()
+ } = workflowStore.getState()
if (runningStatus)
return
handleNodeSelect(node.id)
- }, [handleNodeSelect])
+ }, [handleNodeSelect, workflowStore])
const handleNodeConnect = useCallback(({
source,
@@ -289,7 +290,7 @@ export const useNodesInteractions = () => {
target,
targetHandle,
}) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -338,7 +339,7 @@ export const useNodesInteractions = () => {
})
setEdges(newEdges)
handleSyncWorkflowDraft()
- }, [store, handleSyncWorkflowDraft])
+ }, [store, handleSyncWorkflowDraft, workflowStore])
const handleNodeConnectStart = useCallback((_, { nodeId, handleType }) => {
if (nodeId && handleType) {
@@ -354,7 +355,7 @@ export const useNodesInteractions = () => {
}, [])
const handleNodeDelete = useCallback((nodeId: string) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -387,7 +388,7 @@ export const useNodesInteractions = () => {
})
setEdges(newEdges)
handleSyncWorkflowDraft()
- }, [store, handleSyncWorkflowDraft])
+ }, [store, handleSyncWorkflowDraft, workflowStore])
const handleNodeAdd = useCallback((
{
@@ -403,7 +404,7 @@ export const useNodesInteractions = () => {
nextNodeTargetHandle,
},
) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -565,7 +566,7 @@ export const useNodesInteractions = () => {
setEdges(newEdges)
}
handleSyncWorkflowDraft()
- }, [store, nodesInitialData, handleSyncWorkflowDraft, getAfterNodesInSameBranch])
+ }, [store, nodesInitialData, handleSyncWorkflowDraft, getAfterNodesInSameBranch, workflowStore])
const handleNodeChange = useCallback((
currentNodeId: string,
@@ -573,7 +574,7 @@ export const useNodesInteractions = () => {
sourceHandle: string,
toolDefaultValue?: ToolDefaultValue,
) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -631,7 +632,7 @@ export const useNodesInteractions = () => {
})
setEdges(newEdges)
handleSyncWorkflowDraft()
- }, [store, nodesInitialData, handleSyncWorkflowDraft])
+ }, [store, nodesInitialData, handleSyncWorkflowDraft, workflowStore])
return {
handleNodeDragStart,
diff --git a/web/app/components/workflow/hooks/use-nodes-sync-draft.ts b/web/app/components/workflow/hooks/use-nodes-sync-draft.ts
index c96a451182..a695a4598f 100644
--- a/web/app/components/workflow/hooks/use-nodes-sync-draft.ts
+++ b/web/app/components/workflow/hooks/use-nodes-sync-draft.ts
@@ -5,13 +5,14 @@ import {
useReactFlow,
useStoreApi,
} from 'reactflow'
-import { useStore } from '../store'
+import { useWorkflowStore } 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 workflowStore = useWorkflowStore()
const reactFlow = useReactFlow()
const featuresStore = useFeaturesStore()
@@ -57,10 +58,10 @@ export const useNodesSyncDraft = () => {
},
},
}).then((res) => {
- useStore.setState({ draftUpdatedAt: res.updated_at })
+ workflowStore.setState({ draftUpdatedAt: res.updated_at })
})
}
- }, [store, reactFlow, featuresStore])
+ }, [store, reactFlow, featuresStore, workflowStore])
const { run: debouncedSyncWorkflowDraft } = useDebounceFn(shouldDebouncedSyncWorkflowDraft, {
wait: 2000,
@@ -68,7 +69,7 @@ export const useNodesSyncDraft = () => {
})
const handleSyncWorkflowDraft = useCallback((shouldDelay?: boolean) => {
- const { runningStatus } = useStore.getState()
+ const { runningStatus } = workflowStore.getState()
if (runningStatus)
return
@@ -77,7 +78,7 @@ export const useNodesSyncDraft = () => {
debouncedSyncWorkflowDraft()
else
shouldDebouncedSyncWorkflowDraft()
- }, [debouncedSyncWorkflowDraft, shouldDebouncedSyncWorkflowDraft])
+ }, [debouncedSyncWorkflowDraft, shouldDebouncedSyncWorkflowDraft, workflowStore])
return {
handleSyncWorkflowDraft,
diff --git a/web/app/components/workflow/hooks/use-workflow-run.ts b/web/app/components/workflow/hooks/use-workflow-run.ts
index 76c568c067..e89fd7d61f 100644
--- a/web/app/components/workflow/hooks/use-workflow-run.ts
+++ b/web/app/components/workflow/hooks/use-workflow-run.ts
@@ -7,7 +7,7 @@ import {
useStoreApi,
} from 'reactflow'
import produce from 'immer'
-import { useStore } from '../store'
+import { useWorkflowStore } from '../store'
import {
NodeRunningStatus,
WorkflowRunningStatus,
@@ -19,6 +19,7 @@ import { ssePost } from '@/service/base'
export const useWorkflowRun = () => {
const store = useStoreApi()
+ const workflowStore = useWorkflowStore()
const reactflow = useReactFlow()
const workflowContainerRef = useRef(null)
@@ -30,14 +31,14 @@ export const useWorkflowRun = () => {
} = reactflow
const {
setBackupDraft,
- } = useStore.getState()
+ } = workflowStore.getState()
setBackupDraft({
nodes: getNodes(),
edges: getEdges(),
viewport: getViewport(),
})
- }, [reactflow])
+ }, [reactflow, workflowStore])
const handleLoadBackupDraft = useCallback(() => {
const {
@@ -45,7 +46,7 @@ export const useWorkflowRun = () => {
setEdges,
} = store.getState()
const { setViewport } = reactflow
- const { backupDraft } = useStore.getState()
+ const { backupDraft } = workflowStore.getState()
if (backupDraft) {
const {
@@ -57,10 +58,10 @@ export const useWorkflowRun = () => {
setEdges(edges)
setViewport(viewport)
}
- }, [store, reactflow])
+ }, [store, reactflow, workflowStore])
const handleRunSetting = useCallback((shouldClear?: boolean) => {
- useStore.setState({ runningStatus: shouldClear ? undefined : WorkflowRunningStatus.Waiting })
+ workflowStore.setState({ runningStatus: shouldClear ? undefined : WorkflowRunningStatus.Waiting })
const {
setNodes,
getNodes,
@@ -86,7 +87,7 @@ export const useWorkflowRun = () => {
})
setEdges(newEdges)
}
- }, [store, handleLoadBackupDraft, handleBackupDraft])
+ }, [store, handleLoadBackupDraft, handleBackupDraft, workflowStore])
const handleRun = useCallback((params: any, callback?: IOtherOptions) => {
const {
@@ -117,10 +118,10 @@ export const useWorkflowRun = () => {
},
{
onWorkflowStarted: ({ task_id, workflow_run_id, data }) => {
- useStore.setState({ runningStatus: WorkflowRunningStatus.Running })
- useStore.setState({ taskId: task_id })
- useStore.setState({ currentSequenceNumber: data.sequence_number })
- useStore.setState({ workflowRunId: workflow_run_id })
+ workflowStore.setState({ runningStatus: WorkflowRunningStatus.Running })
+ workflowStore.setState({ taskId: task_id })
+ workflowStore.setState({ currentSequenceNumber: data.sequence_number })
+ workflowStore.setState({ workflowRunId: workflow_run_id })
const newNodes = produce(getNodes(), (draft) => {
draft.forEach((node) => {
node.data._runningStatus = NodeRunningStatus.Waiting
@@ -129,7 +130,7 @@ export const useWorkflowRun = () => {
setNodes(newNodes)
},
onWorkflowFinished: ({ data }) => {
- useStore.setState({ runningStatus: data.status as WorkflowRunningStatus })
+ workflowStore.setState({ runningStatus: data.status as WorkflowRunningStatus })
},
onNodeStarted: ({ data }) => {
const nodes = getNodes()
@@ -171,7 +172,7 @@ export const useWorkflowRun = () => {
...callback,
},
)
- }, [store, reactflow])
+ }, [store, reactflow, workflowStore])
return {
handleBackupDraft,
diff --git a/web/app/components/workflow/hooks/use-workflow.ts b/web/app/components/workflow/hooks/use-workflow.ts
index 4f1e855d30..3a81343c4d 100644
--- a/web/app/components/workflow/hooks/use-workflow.ts
+++ b/web/app/components/workflow/hooks/use-workflow.ts
@@ -17,7 +17,7 @@ import {
} from '../utils'
import type { Node } from '../types'
import { BlockEnum } from '../types'
-import { useStore } from '../store'
+import { useWorkflowStore } from '../store'
import {
START_INITIAL_POSITION,
SUPPORT_OUTPUT_VARS_NODE,
@@ -203,6 +203,7 @@ export const useWorkflow = () => {
}
export const useWorkflowInit = () => {
+ const workflowStore = useWorkflowStore()
const nodesInitialData = useNodesInitialData()
const appDetail = useAppStore(state => state.appDetail)!
const { data, error, mutate } = useSWR(`/apps/${appDetail.id}/workflows/draft`, fetchWorkflowDraft)
@@ -212,14 +213,14 @@ export const useWorkflowInit = () => {
const toolsets = await fetchCollectionList()
const nodesDefaultConfigsData = await fetchNodesDefaultConfigs(`/apps/${appDetail?.id}/workflows/default-workflow-block-configs`)
- useStore.setState({
+ workflowStore.setState({
toolsets,
toolsMap: toolsets.reduce((acc, toolset) => {
acc[toolset.id] = []
return acc
}, {} as ToolsMap),
})
- useStore.setState({
+ workflowStore.setState({
nodesDefaultConfigs: nodesDefaultConfigsData.reduce((acc, block) => {
if (!acc[block.type])
acc[block.type] = block.config
@@ -238,13 +239,13 @@ export const useWorkflowInit = () => {
useEffect(() => {
if (data)
- useStore.setState({ draftUpdatedAt: data.updated_at })
- }, [data])
+ workflowStore.setState({ draftUpdatedAt: data.updated_at })
+ }, [data, workflowStore])
if (error && error.json && !error.bodyUsed && appDetail) {
error.json().then((err: any) => {
if (err.code === 'draft_workflow_not_exist') {
- useStore.setState({ notInitialWorkflow: true })
+ workflowStore.setState({ notInitialWorkflow: true })
syncWorkflowDraft({
url: `/apps/${appDetail.id}/workflows/draft`,
params: {
@@ -261,7 +262,7 @@ export const useWorkflowInit = () => {
features: {},
},
}).then((res) => {
- useStore.setState({ draftUpdatedAt: res.updated_at })
+ workflowStore.setState({ draftUpdatedAt: res.updated_at })
mutate()
})
}
diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx
index 6c827fd407..26da3b90ae 100644
--- a/web/app/components/workflow/index.tsx
+++ b/web/app/components/workflow/index.tsx
@@ -17,6 +17,7 @@ import type {
Edge,
Node,
} from './types'
+import { WorkflowContextProvider } from './context'
import {
useEdgesInteractions,
useNodesInteractions,
@@ -151,30 +152,21 @@ const Workflow: FC = memo(({
Workflow.displayName = 'Workflow'
-const WorkflowWrap: FC = ({
- nodes,
- edges,
-}) => {
+const WorkflowWrap = memo(() => {
const data = useWorkflowInit()
const nodesData = useMemo(() => {
- if (nodes)
- return nodes
-
if (data)
return initialNodes(data.graph.nodes, data.graph.edges)
return []
- }, [data, nodes])
+ }, [data])
const edgesData = useMemo(() => {
- if (edges)
- return edges
-
if (data)
return initialEdges(data.graph.edges)
return []
- }, [data, edges])
+ }, [data])
if (!data) {
return (
@@ -209,6 +201,15 @@ const WorkflowWrap: FC = ({
)
+})
+WorkflowWrap.displayName = 'WorkflowWrap'
+
+const WorkflowContainer = () => {
+ return (
+
+
+
+ )
}
-export default memo(WorkflowWrap)
+export default memo(WorkflowContainer)
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 0fb1ea973a..e5d6dc82ba 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
@@ -3,7 +3,7 @@ import {
useCallback,
useMemo,
} from 'react'
-import { useStore } from '../../store'
+import { useWorkflowStore } from '../../store'
import UserInput from './user-input'
import { useChat } from './hooks'
import Chat from '@/app/components/base/chat/chat'
@@ -19,6 +19,7 @@ const ChatWrapper = () => {
suggestedQuestions,
handleSend,
} = useChat()
+ const workflowStore = useWorkflowStore()
const featuresStore = useFeaturesStore()
const features = featuresStore!.getState().features
@@ -38,10 +39,10 @@ const ChatWrapper = () => {
handleSend({
query,
files,
- inputs: useStore.getState().inputs,
+ inputs: workflowStore.getState().inputs,
conversationId,
})
- }, [conversationId, handleSend])
+ }, [conversationId, handleSend, workflowStore])
return (
{
const { t } = useTranslation()
+ const workflowStore = useWorkflowStore()
const [expanded, setExpanded] = useState(true)
const inputs = useStore(s => s.inputs)
const nodes = useNodes()
@@ -19,7 +23,7 @@ const UserInput = () => {
const variables = startNode?.data.variables || []
const handleValueChange = (variable: string, v: string) => {
- useStore.getState().setInputs({
+ workflowStore.getState().setInputs({
...inputs,
[variable]: v,
})
diff --git a/web/app/components/workflow/panel/inputs-panel.tsx b/web/app/components/workflow/panel/inputs-panel.tsx
index 91a717a8e8..430a072891 100644
--- a/web/app/components/workflow/panel/inputs-panel.tsx
+++ b/web/app/components/workflow/panel/inputs-panel.tsx
@@ -6,13 +6,17 @@ import { useTranslation } from 'react-i18next'
import { useNodes } from 'reactflow'
import FormItem from '../nodes/_base/components/before-run-form/form-item'
import { BlockEnum } from '../types'
-import { useStore } from '../store'
+import {
+ useStore,
+ useWorkflowStore,
+} from '../store'
import { useWorkflowRun } from '../hooks'
import type { StartNodeType } from '../nodes/start/types'
import Button from '@/app/components/base/button'
const InputsPanel = () => {
const { t } = useTranslation()
+ const workflowStore = useWorkflowStore()
const nodes = useNodes()
const inputs = useStore(s => s.inputs)
const {
@@ -23,15 +27,15 @@ const InputsPanel = () => {
const variables = startNode?.data.variables || []
const handleValueChange = (variable: string, v: string) => {
- useStore.getState().setInputs({
+ workflowStore.getState().setInputs({
...inputs,
[variable]: v,
})
}
const handleCancel = useCallback(() => {
- useStore.setState({ showInputsPanel: false })
- }, [])
+ workflowStore.setState({ showInputsPanel: false })
+ }, [workflowStore])
const doRun = () => {
handleCancel()
diff --git a/web/app/components/workflow/panel/run-history.tsx b/web/app/components/workflow/panel/run-history.tsx
index 263d2354e7..1ea4a7fd8a 100644
--- a/web/app/components/workflow/panel/run-history.tsx
+++ b/web/app/components/workflow/panel/run-history.tsx
@@ -6,13 +6,17 @@ import useSWR from 'swr'
import { WorkflowRunningStatus } from '../types'
import { CheckCircle, XClose } from '@/app/components/base/icons/src/vender/line/general'
import { AlertCircle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
-import { useStore as useRunHistoryStore } from '@/app/components/workflow/store'
+import {
+ useStore as useRunHistoryStore,
+ useWorkflowStore,
+} from '@/app/components/workflow/store'
import { useStore as useAppStore } from '@/app/components/app/store'
import { fetchWorkflowRunHistory } from '@/service/workflow'
import Loading from '@/app/components/base/loading'
const RunHistory = () => {
const { t } = useTranslation()
+ const workflowStore = useWorkflowStore()
const appDetail = useAppStore(state => state.appDetail)
const workflowRunId = useRunHistoryStore(state => state.workflowRunId)
const { data, isLoading } = useSWR(appDetail ? `/apps/${appDetail.id}/workflow-runs` : null, fetchWorkflowRunHistory)
@@ -26,7 +30,7 @@ const RunHistory = () => {
{t('workflow.common.runHistory')}
useRunHistoryStore.setState({ showRunHistory: false })}
+ onClick={() => workflowStore.setState({ showRunHistory: false })}
>
@@ -47,7 +51,7 @@ const RunHistory = () => {
'flex mb-0.5 px-2 py-[7px] rounded-lg hover:bg-primary-50 cursor-pointer',
item.id === workflowRunId && 'bg-primary-50',
)}
- onClick={() => useRunHistoryStore.setState({
+ onClick={() => workflowStore.setState({
currentSequenceNumber: item.sequence_number,
workflowRunId: item.id,
runningStatus: item.status as WorkflowRunningStatus,
diff --git a/web/app/components/workflow/store.ts b/web/app/components/workflow/store.ts
index 18fd1224b9..4b10dc372e 100644
--- a/web/app/components/workflow/store.ts
+++ b/web/app/components/workflow/store.ts
@@ -1,5 +1,9 @@
-import { create } from 'zustand'
+import {
+ create,
+ useStore as useZustandStore,
+} from 'zustand'
import type { Viewport } from 'reactflow'
+import { useContext } from 'react'
import type {
HelpLineHorizontalPosition,
HelpLineVerticalPosition,
@@ -15,6 +19,7 @@ import type {
Node,
WorkflowRunningStatus,
} from './types'
+import { WorkflowContext } from './context'
type State = {
mode: Mode
@@ -62,41 +67,55 @@ type Action = {
setNodesDefaultConfigs: (nodesDefaultConfigs: Record) => void
}
-export const useStore = create(set => ({
- mode: Mode.Editing,
- taskId: '',
- setTaskId: taskId => set(() => ({ taskId })),
- currentSequenceNumber: 0,
- setCurrentSequenceNumber: currentSequenceNumber => set(() => ({ currentSequenceNumber })),
- workflowRunId: '',
- setWorkflowRunId: workflowRunId => set(() => ({ workflowRunId })),
- setMode: mode => set(() => ({ mode })),
- showRunHistory: false,
- setShowRunHistory: showRunHistory => set(() => ({ showRunHistory })),
- showFeaturesPanel: false,
- setShowFeaturesPanel: showFeaturesPanel => set(() => ({ showFeaturesPanel })),
- helpLineHorizontal: undefined,
- setHelpLineHorizontal: helpLineHorizontal => set(() => ({ helpLineHorizontal })),
- helpLineVertical: undefined,
- setHelpLineVertical: helpLineVertical => set(() => ({ helpLineVertical })),
- toolsets: [],
- setToolsets: toolsets => set(() => ({ toolsets })),
- toolsMap: {},
- setToolsMap: toolsMap => set(() => ({ toolsMap })),
- draftUpdatedAt: 0,
- setDraftUpdatedAt: draftUpdatedAt => set(() => ({ draftUpdatedAt })),
- publishedAt: 0,
- setPublishedAt: publishedAt => set(() => ({ publishedAt })),
- runningStatus: undefined,
- setRunningStatus: runningStatus => set(() => ({ runningStatus })),
- showInputsPanel: false,
- setShowInputsPanel: showInputsPanel => set(() => ({ showInputsPanel })),
- inputs: {},
- setInputs: inputs => set(() => ({ inputs })),
- backupDraft: undefined,
- setBackupDraft: backupDraft => set(() => ({ backupDraft })),
- notInitialWorkflow: false,
- setNotInitialWorkflow: notInitialWorkflow => set(() => ({ notInitialWorkflow })),
- nodesDefaultConfigs: {},
- setNodesDefaultConfigs: nodesDefaultConfigs => set(() => ({ nodesDefaultConfigs })),
-}))
+export const createWorkflowStore = () => {
+ return create(set => ({
+ mode: Mode.Editing,
+ taskId: '',
+ setTaskId: taskId => set(() => ({ taskId })),
+ currentSequenceNumber: 0,
+ setCurrentSequenceNumber: currentSequenceNumber => set(() => ({ currentSequenceNumber })),
+ workflowRunId: '',
+ setWorkflowRunId: workflowRunId => set(() => ({ workflowRunId })),
+ setMode: mode => set(() => ({ mode })),
+ showRunHistory: false,
+ setShowRunHistory: showRunHistory => set(() => ({ showRunHistory })),
+ showFeaturesPanel: false,
+ setShowFeaturesPanel: showFeaturesPanel => set(() => ({ showFeaturesPanel })),
+ helpLineHorizontal: undefined,
+ setHelpLineHorizontal: helpLineHorizontal => set(() => ({ helpLineHorizontal })),
+ helpLineVertical: undefined,
+ setHelpLineVertical: helpLineVertical => set(() => ({ helpLineVertical })),
+ toolsets: [],
+ setToolsets: toolsets => set(() => ({ toolsets })),
+ toolsMap: {},
+ setToolsMap: toolsMap => set(() => ({ toolsMap })),
+ draftUpdatedAt: 0,
+ setDraftUpdatedAt: draftUpdatedAt => set(() => ({ draftUpdatedAt })),
+ publishedAt: 0,
+ setPublishedAt: publishedAt => set(() => ({ publishedAt })),
+ runningStatus: undefined,
+ setRunningStatus: runningStatus => set(() => ({ runningStatus })),
+ showInputsPanel: false,
+ setShowInputsPanel: showInputsPanel => set(() => ({ showInputsPanel })),
+ inputs: {},
+ setInputs: inputs => set(() => ({ inputs })),
+ backupDraft: undefined,
+ setBackupDraft: backupDraft => set(() => ({ backupDraft })),
+ notInitialWorkflow: false,
+ setNotInitialWorkflow: notInitialWorkflow => set(() => ({ notInitialWorkflow })),
+ nodesDefaultConfigs: {},
+ setNodesDefaultConfigs: nodesDefaultConfigs => set(() => ({ nodesDefaultConfigs })),
+ }))
+}
+
+export function useStore(selector: (state: State & Action) => T): T {
+ const store = useContext(WorkflowContext)
+ if (!store)
+ throw new Error('Missing WorkflowContext.Provider in the tree')
+
+ return useZustandStore(store, selector)
+}
+
+export const useWorkflowStore = () => {
+ return useContext(WorkflowContext)!
+}