This commit is contained in:
StyleZhang 2024-03-15 16:58:29 +08:00
parent 75b332695b
commit e98456b025
16 changed files with 209 additions and 176 deletions

View File

@ -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 (
<div className='w-full h-full overflow-x-auto'>
<Workflow
// nodes={nodes}
// edges={edges}
/>
<div className='w-full h-full overflow-x-auto' key={appDetail.id}>
<Workflow />
</div>
)
}

View File

@ -0,0 +1,24 @@
import {
createContext,
useRef,
} from 'react'
import { createWorkflowStore } from './store'
type WorkflowStore = ReturnType<typeof createWorkflowStore>
export const WorkflowContext = createContext<WorkflowStore | null>(null)
type WorkflowProviderProps = {
children: React.ReactNode
}
export const WorkflowContextProvider = ({ children }: WorkflowProviderProps) => {
const storeRef = useRef<WorkflowStore>()
if (!storeRef.current)
storeRef.current = createWorkflowStore()
return (
<WorkflowContext.Provider value={storeRef.current}>
{children}
</WorkflowContext.Provider>
)
}

View File

@ -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)

View File

@ -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 })}
>
<ClockPlay className={`w-4 h-4 ${showRunHistory ? 'text-primary-600' : 'text-gray-500'}`} />
</div>

View File

@ -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<EdgeMouseHandler>((_, 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<EdgeMouseHandler>((_, 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<OnEdgesChange>((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 {

View File

@ -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,

View File

@ -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<NodeDragHandler>((_, node) => {
const {
runningStatus,
} = useStore.getState()
} = workflowStore.getState()
if (runningStatus)
return
dragNodeStartPosition.current = { x: node.position.x, y: node.position.y }
}, [])
}, [workflowStore])
const handleNodeDrag = useCallback<NodeDragHandler>((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<NodeDragHandler>((_, 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<NodeMouseHandler>((_, 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<NodeMouseHandler>(() => {
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<NodeMouseHandler>((_, node) => {
const {
runningStatus,
} = useStore.getState()
} = workflowStore.getState()
if (runningStatus)
return
handleNodeSelect(node.id)
}, [handleNodeSelect])
}, [handleNodeSelect, workflowStore])
const handleNodeConnect = useCallback<OnConnect>(({
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<OnConnectStart>((_, { 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<OnNodeAdd>((
{
@ -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,

View File

@ -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,

View File

@ -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<HTMLDivElement>(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,

View File

@ -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()
})
}

View File

@ -17,6 +17,7 @@ import type {
Edge,
Node,
} from './types'
import { WorkflowContextProvider } from './context'
import {
useEdgesInteractions,
useNodesInteractions,
@ -151,30 +152,21 @@ const Workflow: FC<WorkflowProps> = memo(({
Workflow.displayName = 'Workflow'
const WorkflowWrap: FC<WorkflowProps> = ({
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<WorkflowProps> = ({
</FeaturesProvider>
</ReactFlowProvider>
)
})
WorkflowWrap.displayName = 'WorkflowWrap'
const WorkflowContainer = () => {
return (
<WorkflowContextProvider>
<WorkflowWrap />
</WorkflowContextProvider>
)
}
export default memo(WorkflowWrap)
export default memo(WorkflowContainer)

View File

@ -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 (
<Chat

View File

@ -6,12 +6,16 @@ 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 type { StartNodeType } from '../../nodes/start/types'
import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
const UserInput = () => {
const { t } = useTranslation()
const workflowStore = useWorkflowStore()
const [expanded, setExpanded] = useState(true)
const inputs = useStore(s => s.inputs)
const nodes = useNodes<StartNodeType>()
@ -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,
})

View File

@ -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<StartNodeType>()
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()

View File

@ -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')}
<div
className='flex items-center justify-center w-6 h-6 cursor-pointer'
onClick={() => useRunHistoryStore.setState({ showRunHistory: false })}
onClick={() => workflowStore.setState({ showRunHistory: false })}
>
<XClose className='w-4 h-4 text-gray-500' />
</div>
@ -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,

View File

@ -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<string, any>) => void
}
export const useStore = create<State & Action>(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<State & Action>(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<T>(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)!
}