mirror of
http://112.124.100.131/huang.ze/ebiz-dify-ai.git
synced 2025-12-11 03:46:52 +08:00
feat: workflow remove preview mode (#3941)
This commit is contained in:
@@ -7,3 +7,5 @@ export * from './use-workflow'
|
||||
export * from './use-workflow-run'
|
||||
export * from './use-workflow-template'
|
||||
export * from './use-checklist'
|
||||
export * from './use-workflow-mode'
|
||||
export * from './use-workflow-interactions'
|
||||
|
||||
@@ -201,6 +201,20 @@ export const useEdgesInteractions = () => {
|
||||
setEdges(newEdges)
|
||||
}, [store])
|
||||
|
||||
const handleEdgeCancelRunningStatus = useCallback(() => {
|
||||
const {
|
||||
edges,
|
||||
setEdges,
|
||||
} = store.getState()
|
||||
|
||||
const newEdges = produce(edges, (draft) => {
|
||||
draft.forEach((edge) => {
|
||||
edge.data._runned = false
|
||||
})
|
||||
})
|
||||
setEdges(newEdges)
|
||||
}, [store])
|
||||
|
||||
return {
|
||||
handleEdgeEnter,
|
||||
handleEdgeLeave,
|
||||
@@ -208,5 +222,6 @@ export const useEdgesInteractions = () => {
|
||||
handleEdgeDelete,
|
||||
handleEdgesChange,
|
||||
handleVariableAssignerEdgesChange,
|
||||
handleEdgeCancelRunningStatus,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,9 +243,6 @@ export const useNodesInteractions = () => {
|
||||
}, [store, getNodesReadOnly])
|
||||
|
||||
const handleNodeSelect = useCallback((nodeId: string, cancelSelection?: boolean) => {
|
||||
if (getNodesReadOnly() && !workflowStore.getState().isRestoring)
|
||||
return
|
||||
|
||||
const {
|
||||
getNodes,
|
||||
setNodes,
|
||||
@@ -289,14 +286,11 @@ export const useNodesInteractions = () => {
|
||||
setEdges(newEdges)
|
||||
|
||||
handleSyncWorkflowDraft()
|
||||
}, [store, handleSyncWorkflowDraft, getNodesReadOnly, workflowStore])
|
||||
}, [store, handleSyncWorkflowDraft])
|
||||
|
||||
const handleNodeClick = useCallback<NodeMouseHandler>((_, node) => {
|
||||
if (getNodesReadOnly() && !workflowStore.getState().isRestoring)
|
||||
return
|
||||
|
||||
handleNodeSelect(node.id)
|
||||
}, [handleNodeSelect, getNodesReadOnly, workflowStore])
|
||||
}, [handleNodeSelect])
|
||||
|
||||
const handleNodeConnect = useCallback<OnConnect>(({
|
||||
source,
|
||||
@@ -834,6 +828,36 @@ export const useNodesInteractions = () => {
|
||||
handleNodeDelete(node.id)
|
||||
}, [getNodesReadOnly, handleNodeDelete, store, workflowStore])
|
||||
|
||||
const handleNodeCancelRunningStatus = useCallback(() => {
|
||||
const {
|
||||
getNodes,
|
||||
setNodes,
|
||||
} = store.getState()
|
||||
|
||||
const nodes = getNodes()
|
||||
const newNodes = produce(nodes, (draft) => {
|
||||
draft.forEach((node) => {
|
||||
node.data._runningStatus = undefined
|
||||
})
|
||||
})
|
||||
setNodes(newNodes)
|
||||
}, [store])
|
||||
|
||||
const handleNodesCancelSelected = useCallback(() => {
|
||||
const {
|
||||
getNodes,
|
||||
setNodes,
|
||||
} = store.getState()
|
||||
|
||||
const nodes = getNodes()
|
||||
const newNodes = produce(nodes, (draft) => {
|
||||
draft.forEach((node) => {
|
||||
node.data.selected = false
|
||||
})
|
||||
})
|
||||
setNodes(newNodes)
|
||||
}, [store])
|
||||
|
||||
return {
|
||||
handleNodeDragStart,
|
||||
handleNodeDrag,
|
||||
@@ -853,5 +877,7 @@ export const useNodesInteractions = () => {
|
||||
handleNodeCut,
|
||||
handleNodeDeleteSelected,
|
||||
handleNodePaste,
|
||||
handleNodeCancelRunningStatus,
|
||||
handleNodesCancelSelected,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,8 @@ export const useNodesSyncDraft = () => {
|
||||
}, [store, featuresStore, workflowStore])
|
||||
|
||||
const syncWorkflowDraftWhenPageClose = useCallback(() => {
|
||||
if (getNodesReadOnly())
|
||||
return
|
||||
const postParams = getPostParams()
|
||||
|
||||
if (postParams) {
|
||||
@@ -89,16 +91,18 @@ export const useNodesSyncDraft = () => {
|
||||
JSON.stringify(postParams.params),
|
||||
)
|
||||
}
|
||||
}, [getPostParams, params.appId])
|
||||
}, [getPostParams, params.appId, getNodesReadOnly])
|
||||
|
||||
const doSyncWorkflowDraft = useCallback(async (appId?: string) => {
|
||||
if (getNodesReadOnly())
|
||||
return
|
||||
const postParams = getPostParams(appId)
|
||||
|
||||
if (postParams) {
|
||||
const res = await syncWorkflowDraft(postParams)
|
||||
workflowStore.getState().setDraftUpdatedAt(res.updated_at)
|
||||
}
|
||||
}, [workflowStore, getPostParams])
|
||||
}, [workflowStore, getPostParams, getNodesReadOnly])
|
||||
|
||||
const handleSyncWorkflowDraft = useCallback((sync?: boolean, appId?: string) => {
|
||||
if (getNodesReadOnly())
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useReactFlow } from 'reactflow'
|
||||
import { useWorkflowStore } from '../store'
|
||||
import { WORKFLOW_DATA_UPDATE } from '../constants'
|
||||
import type { WorkflowDataUpdator } from '../types'
|
||||
import {
|
||||
initialEdges,
|
||||
initialNodes,
|
||||
} from '../utils'
|
||||
import { useEdgesInteractions } from './use-edges-interactions'
|
||||
import { useNodesInteractions } from './use-nodes-interactions'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
|
||||
export const useWorkflowInteractions = () => {
|
||||
const reactflow = useReactFlow()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const { handleNodeCancelRunningStatus } = useNodesInteractions()
|
||||
const { handleEdgeCancelRunningStatus } = useEdgesInteractions()
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
|
||||
const handleCancelDebugAndPreviewPanel = useCallback(() => {
|
||||
workflowStore.setState({
|
||||
showDebugAndPreviewPanel: false,
|
||||
})
|
||||
handleNodeCancelRunningStatus()
|
||||
handleEdgeCancelRunningStatus()
|
||||
}, [workflowStore, handleNodeCancelRunningStatus, handleEdgeCancelRunningStatus])
|
||||
|
||||
const handleUpdateWorkflowCanvas = useCallback((payload: WorkflowDataUpdator) => {
|
||||
const {
|
||||
nodes,
|
||||
edges,
|
||||
viewport,
|
||||
} = payload
|
||||
const { setViewport } = reactflow
|
||||
eventEmitter?.emit({
|
||||
type: WORKFLOW_DATA_UPDATE,
|
||||
payload: {
|
||||
nodes: initialNodes(nodes, edges),
|
||||
edges: initialEdges(edges, nodes),
|
||||
},
|
||||
} as any)
|
||||
setViewport(viewport)
|
||||
}, [eventEmitter, reactflow])
|
||||
|
||||
return {
|
||||
handleCancelDebugAndPreviewPanel,
|
||||
handleUpdateWorkflowCanvas,
|
||||
}
|
||||
}
|
||||
14
web/app/components/workflow/hooks/use-workflow-mode.ts
Normal file
14
web/app/components/workflow/hooks/use-workflow-mode.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useStore } from '../store'
|
||||
|
||||
export const useWorkflowMode = () => {
|
||||
const historyWorkflowData = useStore(s => s.historyWorkflowData)
|
||||
const isRestoring = useStore(s => s.isRestoring)
|
||||
return useMemo(() => {
|
||||
return {
|
||||
normal: !historyWorkflowData && !isRestoring,
|
||||
restoring: isRestoring,
|
||||
viewHistory: !!historyWorkflowData,
|
||||
}
|
||||
}, [historyWorkflowData, isRestoring])
|
||||
}
|
||||
@@ -5,11 +5,12 @@ import {
|
||||
} from 'reactflow'
|
||||
import produce from 'immer'
|
||||
import { useWorkflowStore } from '../store'
|
||||
import { useNodesSyncDraft } from '../hooks'
|
||||
import {
|
||||
NodeRunningStatus,
|
||||
WorkflowRunningStatus,
|
||||
} from '../types'
|
||||
import { useWorkflow } from './use-workflow'
|
||||
import { useWorkflowInteractions } from './use-workflow-interactions'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import type { IOtherOptions } from '@/service/base'
|
||||
import { ssePost } from '@/service/base'
|
||||
@@ -24,7 +25,8 @@ export const useWorkflowRun = () => {
|
||||
const workflowStore = useWorkflowStore()
|
||||
const reactflow = useReactFlow()
|
||||
const featuresStore = useFeaturesStore()
|
||||
const { renderTreeFromRecord } = useWorkflow()
|
||||
const { doSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const { handleUpdateWorkflowCanvas } = useWorkflowInteractions()
|
||||
|
||||
const handleBackupDraft = useCallback(() => {
|
||||
const {
|
||||
@@ -45,15 +47,11 @@ export const useWorkflowRun = () => {
|
||||
viewport: getViewport(),
|
||||
features,
|
||||
})
|
||||
doSyncWorkflowDraft()
|
||||
}
|
||||
}, [reactflow, workflowStore, store, featuresStore])
|
||||
}, [reactflow, workflowStore, store, featuresStore, doSyncWorkflowDraft])
|
||||
|
||||
const handleLoadBackupDraft = useCallback(() => {
|
||||
const {
|
||||
setNodes,
|
||||
setEdges,
|
||||
} = store.getState()
|
||||
const { setViewport } = reactflow
|
||||
const {
|
||||
backupDraft,
|
||||
setBackupDraft,
|
||||
@@ -66,64 +64,32 @@ export const useWorkflowRun = () => {
|
||||
viewport,
|
||||
features,
|
||||
} = backupDraft
|
||||
setNodes(nodes)
|
||||
setEdges(edges)
|
||||
setViewport(viewport)
|
||||
handleUpdateWorkflowCanvas({
|
||||
nodes,
|
||||
edges,
|
||||
viewport,
|
||||
})
|
||||
featuresStore!.setState({ features })
|
||||
setBackupDraft(undefined)
|
||||
}
|
||||
}, [store, reactflow, workflowStore, featuresStore])
|
||||
}, [handleUpdateWorkflowCanvas, workflowStore, featuresStore])
|
||||
|
||||
const handleRunSetting = useCallback((shouldClear?: boolean) => {
|
||||
if (shouldClear) {
|
||||
workflowStore.setState({
|
||||
workflowRunningData: undefined,
|
||||
historyWorkflowData: undefined,
|
||||
showInputsPanel: false,
|
||||
})
|
||||
}
|
||||
else {
|
||||
workflowStore.setState({
|
||||
workflowRunningData: {
|
||||
result: {
|
||||
status: shouldClear ? '' : WorkflowRunningStatus.Waiting,
|
||||
},
|
||||
tracing: [],
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const {
|
||||
setNodes,
|
||||
getNodes,
|
||||
edges,
|
||||
setEdges,
|
||||
} = store.getState()
|
||||
|
||||
if (shouldClear) {
|
||||
handleLoadBackupDraft()
|
||||
}
|
||||
else {
|
||||
handleBackupDraft()
|
||||
const newNodes = produce(getNodes(), (draft) => {
|
||||
draft.forEach((node) => {
|
||||
node.data._runningStatus = NodeRunningStatus.Waiting
|
||||
})
|
||||
})
|
||||
setNodes(newNodes)
|
||||
const newEdges = produce(edges, (draft) => {
|
||||
draft.forEach((edge) => {
|
||||
edge.data._runned = false
|
||||
})
|
||||
})
|
||||
setEdges(newEdges)
|
||||
}
|
||||
}, [store, handleLoadBackupDraft, handleBackupDraft, workflowStore])
|
||||
|
||||
const handleRun = useCallback((
|
||||
const handleRun = useCallback(async (
|
||||
params: any,
|
||||
callback?: IOtherOptions,
|
||||
) => {
|
||||
const {
|
||||
getNodes,
|
||||
setNodes,
|
||||
} = store.getState()
|
||||
const newNodes = produce(getNodes(), (draft) => {
|
||||
draft.forEach((node) => {
|
||||
node.data.selected = false
|
||||
})
|
||||
})
|
||||
setNodes(newNodes)
|
||||
await doSyncWorkflowDraft()
|
||||
|
||||
const {
|
||||
onWorkflowStarted,
|
||||
onWorkflowFinished,
|
||||
@@ -151,15 +117,14 @@ export const useWorkflowRun = () => {
|
||||
let prevNodeId = ''
|
||||
|
||||
const {
|
||||
workflowRunningData,
|
||||
setWorkflowRunningData,
|
||||
} = workflowStore.getState()
|
||||
setWorkflowRunningData(produce(workflowRunningData!, (draft) => {
|
||||
draft.result = {
|
||||
...draft?.result,
|
||||
setWorkflowRunningData({
|
||||
result: {
|
||||
status: WorkflowRunningStatus.Running,
|
||||
}
|
||||
}))
|
||||
},
|
||||
tracing: [],
|
||||
})
|
||||
|
||||
ssePost(
|
||||
url,
|
||||
@@ -174,8 +139,6 @@ export const useWorkflowRun = () => {
|
||||
setWorkflowRunningData,
|
||||
} = workflowStore.getState()
|
||||
const {
|
||||
getNodes,
|
||||
setNodes,
|
||||
edges,
|
||||
setEdges,
|
||||
} = store.getState()
|
||||
@@ -188,12 +151,6 @@ export const useWorkflowRun = () => {
|
||||
}
|
||||
}))
|
||||
|
||||
const newNodes = produce(getNodes(), (draft) => {
|
||||
draft.forEach((node) => {
|
||||
node.data._runningStatus = NodeRunningStatus.Waiting
|
||||
})
|
||||
})
|
||||
setNodes(newNodes)
|
||||
const newEdges = produce(edges, (draft) => {
|
||||
draft.forEach((edge) => {
|
||||
edge.data = {
|
||||
@@ -253,6 +210,7 @@ export const useWorkflowRun = () => {
|
||||
setNodes,
|
||||
edges,
|
||||
setEdges,
|
||||
transform,
|
||||
} = store.getState()
|
||||
const nodes = getNodes()
|
||||
setWorkflowRunningData(produce(workflowRunningData!, (draft) => {
|
||||
@@ -268,12 +226,12 @@ export const useWorkflowRun = () => {
|
||||
const currentNodeIndex = nodes.findIndex(node => node.id === data.node_id)
|
||||
const currentNode = nodes[currentNodeIndex]
|
||||
const position = currentNode.position
|
||||
const zoom = 1
|
||||
const zoom = transform[2]
|
||||
|
||||
setViewport({
|
||||
x: (clientWidth - 400 - currentNode.width!) / 2 - position.x,
|
||||
y: (clientHeight - currentNode.height!) / 2 - position.y,
|
||||
zoom,
|
||||
x: (clientWidth - 400 - currentNode.width! * zoom) / 2 - position.x * zoom,
|
||||
y: (clientHeight - currentNode.height! * zoom) / 2 - position.y * zoom,
|
||||
zoom: transform[2],
|
||||
})
|
||||
const newNodes = produce(nodes, (draft) => {
|
||||
draft[currentNodeIndex].data._runningStatus = NodeRunningStatus.Running
|
||||
@@ -329,7 +287,7 @@ export const useWorkflowRun = () => {
|
||||
...restCallback,
|
||||
},
|
||||
)
|
||||
}, [store, reactflow, workflowStore])
|
||||
}, [store, reactflow, workflowStore, doSyncWorkflowDraft])
|
||||
|
||||
const handleStopRun = useCallback((taskId: string) => {
|
||||
const appId = useAppStore.getState().appDetail?.id
|
||||
@@ -344,18 +302,21 @@ export const useWorkflowRun = () => {
|
||||
if (publishedWorkflow) {
|
||||
const nodes = publishedWorkflow.graph.nodes
|
||||
const edges = publishedWorkflow.graph.edges
|
||||
const viewport = publishedWorkflow.graph.viewport
|
||||
const viewport = publishedWorkflow.graph.viewport!
|
||||
|
||||
renderTreeFromRecord(nodes, edges, viewport)
|
||||
handleUpdateWorkflowCanvas({
|
||||
nodes,
|
||||
edges,
|
||||
viewport,
|
||||
})
|
||||
featuresStore?.setState({ features: publishedWorkflow.features })
|
||||
workflowStore.getState().setPublishedAt(publishedWorkflow.created_at)
|
||||
}
|
||||
}, [featuresStore, workflowStore, renderTreeFromRecord])
|
||||
}, [featuresStore, handleUpdateWorkflowCanvas, workflowStore])
|
||||
|
||||
return {
|
||||
handleBackupDraft,
|
||||
handleLoadBackupDraft,
|
||||
handleRunSetting,
|
||||
handleRun,
|
||||
handleStopRun,
|
||||
handleRestoreFromPublishedWorkflow,
|
||||
|
||||
@@ -16,15 +16,11 @@ import {
|
||||
} from 'reactflow'
|
||||
import type {
|
||||
Connection,
|
||||
Viewport,
|
||||
} from 'reactflow'
|
||||
import {
|
||||
getLayoutByDagre,
|
||||
initialEdges,
|
||||
initialNodes,
|
||||
} from '../utils'
|
||||
import type {
|
||||
Edge,
|
||||
Node,
|
||||
ValueSelector,
|
||||
} from '../types'
|
||||
@@ -39,7 +35,6 @@ import {
|
||||
import {
|
||||
AUTO_LAYOUT_OFFSET,
|
||||
SUPPORT_OUTPUT_VARS_NODE,
|
||||
WORKFLOW_DATA_UPDATE,
|
||||
} from '../constants'
|
||||
import { findUsedVarNodes, getNodeOutputVars, updateNodeVars } from '../nodes/_base/components/variable/utils'
|
||||
import { useNodesExtraData } from './use-nodes-data'
|
||||
@@ -58,7 +53,6 @@ import {
|
||||
fetchAllCustomTools,
|
||||
} from '@/service/tools'
|
||||
import I18n from '@/context/i18n'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
|
||||
export const useIsChatMode = () => {
|
||||
const appDetail = useAppStore(s => s.appDetail)
|
||||
@@ -73,7 +67,6 @@ export const useWorkflow = () => {
|
||||
const workflowStore = useWorkflowStore()
|
||||
const nodesExtraData = useNodesExtraData()
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
|
||||
const setPanelWidth = useCallback((width: number) => {
|
||||
localStorage.setItem('workflow-node-panel-width', `${width}`)
|
||||
@@ -323,23 +316,6 @@ export const useWorkflow = () => {
|
||||
return dayjs(time).locale(locale === 'zh-Hans' ? 'zh-cn' : locale).fromNow()
|
||||
}, [locale])
|
||||
|
||||
const renderTreeFromRecord = useCallback((nodes: Node[], edges: Edge[], viewport?: Viewport) => {
|
||||
const { setViewport } = reactflow
|
||||
|
||||
const nodesMap = nodes.map(node => ({ ...node, data: { ...node.data, selected: false } }))
|
||||
|
||||
eventEmitter?.emit({
|
||||
type: WORKFLOW_DATA_UPDATE,
|
||||
payload: {
|
||||
nodes: initialNodes(nodesMap, edges),
|
||||
edges: initialEdges(edges, nodesMap),
|
||||
},
|
||||
} as any)
|
||||
|
||||
if (viewport)
|
||||
setViewport(viewport)
|
||||
}, [reactflow, eventEmitter])
|
||||
|
||||
const getNode = useCallback((nodeId?: string) => {
|
||||
const { getNodes } = store.getState()
|
||||
const nodes = getNodes()
|
||||
@@ -369,7 +345,6 @@ export const useWorkflow = () => {
|
||||
isNodeVarsUsedInNodes,
|
||||
isValidConnection,
|
||||
formatTimeFromNow,
|
||||
renderTreeFromRecord,
|
||||
getNode,
|
||||
getBeforeNodeById,
|
||||
enableShortcuts,
|
||||
@@ -510,11 +485,11 @@ export const useNodesReadOnly = () => {
|
||||
isRestoring,
|
||||
} = workflowStore.getState()
|
||||
|
||||
return workflowRunningData || historyWorkflowData || isRestoring
|
||||
return workflowRunningData?.result.status === WorkflowRunningStatus.Running || historyWorkflowData || isRestoring
|
||||
}, [workflowStore])
|
||||
|
||||
return {
|
||||
nodesReadOnly: !!(workflowRunningData || historyWorkflowData || isRestoring),
|
||||
nodesReadOnly: !!(workflowRunningData?.result.status === WorkflowRunningStatus.Running || historyWorkflowData || isRestoring),
|
||||
getNodesReadOnly,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user