mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 04:26:30 +08:00
sync nodes
This commit is contained in:
parent
2398ed6fe8
commit
e240175116
@ -4,7 +4,6 @@ import {
|
|||||||
import produce from 'immer'
|
import produce from 'immer'
|
||||||
import {
|
import {
|
||||||
useReactFlow,
|
useReactFlow,
|
||||||
useStoreApi,
|
|
||||||
useViewport,
|
useViewport,
|
||||||
} from 'reactflow'
|
} from 'reactflow'
|
||||||
import { useEventListener } from 'ahooks'
|
import { useEventListener } from 'ahooks'
|
||||||
@ -19,9 +18,9 @@ import CustomNode from './nodes'
|
|||||||
import CustomNoteNode from './note-node'
|
import CustomNoteNode from './note-node'
|
||||||
import { CUSTOM_NOTE_NODE } from './note-node/constants'
|
import { CUSTOM_NOTE_NODE } from './note-node/constants'
|
||||||
import { BlockEnum } from './types'
|
import { BlockEnum } from './types'
|
||||||
|
import { useCollaborativeWorkflow } from '@/app/components/workflow/hooks/use-collaborative-workflow'
|
||||||
|
|
||||||
const CandidateNode = () => {
|
const CandidateNode = () => {
|
||||||
const store = useStoreApi()
|
|
||||||
const reactflow = useReactFlow()
|
const reactflow = useReactFlow()
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
const candidateNode = useStore(s => s.candidateNode)
|
const candidateNode = useStore(s => s.candidateNode)
|
||||||
@ -29,18 +28,15 @@ const CandidateNode = () => {
|
|||||||
const { zoom } = useViewport()
|
const { zoom } = useViewport()
|
||||||
const { handleNodeSelect } = useNodesInteractions()
|
const { handleNodeSelect } = useNodesInteractions()
|
||||||
const { saveStateToHistory } = useWorkflowHistory()
|
const { saveStateToHistory } = useWorkflowHistory()
|
||||||
|
const collaborativeWorkflow = useCollaborativeWorkflow()
|
||||||
|
|
||||||
useEventListener('click', (e) => {
|
useEventListener('click', (e) => {
|
||||||
const { candidateNode, mousePosition } = workflowStore.getState()
|
const { candidateNode, mousePosition } = workflowStore.getState()
|
||||||
|
|
||||||
if (candidateNode) {
|
if (candidateNode) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const {
|
const { nodes, setNodes } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
setNodes,
|
|
||||||
} = store.getState()
|
|
||||||
const { screenToFlowPosition } = reactflow
|
const { screenToFlowPosition } = reactflow
|
||||||
const nodes = getNodes()
|
|
||||||
const { x, y } = screenToFlowPosition({ x: mousePosition.pageX, y: mousePosition.pageY })
|
const { x, y } = screenToFlowPosition({ x: mousePosition.pageX, y: mousePosition.pageY })
|
||||||
const newNodes = produce(nodes, (draft) => {
|
const newNodes = produce(nodes, (draft) => {
|
||||||
draft.push({
|
draft.push({
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
useCallback,
|
useCallback,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import { useReactFlow, useStoreApi } from 'reactflow'
|
import { useReactFlow } from 'reactflow'
|
||||||
import produce from 'immer'
|
import produce from 'immer'
|
||||||
import { useStore, useWorkflowStore } from '../store'
|
import { useStore, useWorkflowStore } from '../store'
|
||||||
import {
|
import {
|
||||||
@ -28,6 +28,7 @@ import { useNodesInteractionsWithoutSync } from './use-nodes-interactions-withou
|
|||||||
import { useNodesSyncDraft } from './use-nodes-sync-draft'
|
import { useNodesSyncDraft } from './use-nodes-sync-draft'
|
||||||
import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history'
|
import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history'
|
||||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||||
|
import { useCollaborativeWorkflow } from '@/app/components/workflow/hooks/use-collaborative-workflow'
|
||||||
|
|
||||||
export const useWorkflowInteractions = () => {
|
export const useWorkflowInteractions = () => {
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
@ -87,23 +88,22 @@ export const useWorkflowMoveMode = () => {
|
|||||||
|
|
||||||
export const useWorkflowOrganize = () => {
|
export const useWorkflowOrganize = () => {
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
const store = useStoreApi()
|
|
||||||
const reactflow = useReactFlow()
|
const reactflow = useReactFlow()
|
||||||
const { getNodesReadOnly } = useNodesReadOnly()
|
const { getNodesReadOnly } = useNodesReadOnly()
|
||||||
const { saveStateToHistory } = useWorkflowHistory()
|
const { saveStateToHistory } = useWorkflowHistory()
|
||||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||||
|
const collaborativeWorkflow = useCollaborativeWorkflow()
|
||||||
|
|
||||||
const handleLayout = useCallback(async () => {
|
const handleLayout = useCallback(async () => {
|
||||||
if (getNodesReadOnly())
|
if (getNodesReadOnly())
|
||||||
return
|
return
|
||||||
workflowStore.setState({ nodeAnimation: true })
|
workflowStore.setState({ nodeAnimation: true })
|
||||||
const {
|
const {
|
||||||
getNodes,
|
nodes,
|
||||||
edges,
|
edges,
|
||||||
setNodes,
|
setNodes,
|
||||||
} = store.getState()
|
} = collaborativeWorkflow.getState()
|
||||||
const { setViewport } = reactflow
|
const { setViewport } = reactflow
|
||||||
const nodes = getNodes()
|
|
||||||
|
|
||||||
const loopAndIterationNodes = nodes.filter(
|
const loopAndIterationNodes = nodes.filter(
|
||||||
node => (node.data.type === BlockEnum.Loop || node.data.type === BlockEnum.Iteration)
|
node => (node.data.type === BlockEnum.Loop || node.data.type === BlockEnum.Iteration)
|
||||||
@ -248,7 +248,7 @@ export const useWorkflowOrganize = () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
handleSyncWorkflowDraft()
|
handleSyncWorkflowDraft()
|
||||||
})
|
})
|
||||||
}, [getNodesReadOnly, store, reactflow, workflowStore, handleSyncWorkflowDraft, saveStateToHistory])
|
}, [getNodesReadOnly, collaborativeWorkflow, reactflow, workflowStore, handleSyncWorkflowDraft, saveStateToHistory])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleLayout,
|
handleLayout,
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import {
|
import {
|
||||||
getIncomers,
|
getIncomers,
|
||||||
getOutgoers,
|
getOutgoers,
|
||||||
useStoreApi,
|
|
||||||
} from 'reactflow'
|
} from 'reactflow'
|
||||||
import type {
|
import type {
|
||||||
Connection,
|
Connection,
|
||||||
@ -35,6 +34,7 @@ import { CUSTOM_NOTE_NODE } from '../note-node/constants'
|
|||||||
import { findUsedVarNodes, getNodeOutputVars, updateNodeVars } from '../nodes/_base/components/variable/utils'
|
import { findUsedVarNodes, getNodeOutputVars, updateNodeVars } from '../nodes/_base/components/variable/utils'
|
||||||
import { useAvailableBlocks } from './use-available-blocks'
|
import { useAvailableBlocks } from './use-available-blocks'
|
||||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||||
|
import { useCollaborativeWorkflow } from '@/app/components/workflow/hooks/use-collaborative-workflow'
|
||||||
import {
|
import {
|
||||||
fetchAllBuiltInTools,
|
fetchAllBuiltInTools,
|
||||||
fetchAllCustomTools,
|
fetchAllCustomTools,
|
||||||
@ -55,26 +55,19 @@ export const useIsChatMode = () => {
|
|||||||
|
|
||||||
export const useWorkflow = () => {
|
export const useWorkflow = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const store = useStoreApi()
|
const collaborativeWorkflow = useCollaborativeWorkflow()
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
const { getAvailableBlocks } = useAvailableBlocks()
|
const { getAvailableBlocks } = useAvailableBlocks()
|
||||||
const { nodesMap } = useNodesMetaData()
|
const { nodesMap } = useNodesMetaData()
|
||||||
|
|
||||||
const getNodeById = useCallback((nodeId: string) => {
|
const getNodeById = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
const currentNode = nodes.find(node => node.id === nodeId)
|
const currentNode = nodes.find(node => node.id === nodeId)
|
||||||
return currentNode
|
return currentNode
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const getTreeLeafNodes = useCallback((nodeId: string) => {
|
const getTreeLeafNodes = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes, edges } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
edges,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
const currentNode = nodes.find(node => node.id === nodeId)
|
const currentNode = nodes.find(node => node.id === nodeId)
|
||||||
|
|
||||||
let startNodes = nodes.filter(node => nodesMap?.[node.data.type as BlockEnum]?.metaData.isStart) || []
|
let startNodes = nodes.filter(node => nodesMap?.[node.data.type as BlockEnum]?.metaData.isStart) || []
|
||||||
@ -117,14 +110,11 @@ export const useWorkflow = () => {
|
|||||||
return uniqBy(list, 'id').filter((item: Node) => {
|
return uniqBy(list, 'id').filter((item: Node) => {
|
||||||
return SUPPORT_OUTPUT_VARS_NODE.includes(item.data.type)
|
return SUPPORT_OUTPUT_VARS_NODE.includes(item.data.type)
|
||||||
})
|
})
|
||||||
}, [store, nodesMap])
|
}, [collaborativeWorkflow, nodesMap])
|
||||||
|
|
||||||
const getBeforeNodesInSameBranch = useCallback((nodeId: string, newNodes?: Node[], newEdges?: Edge[]) => {
|
const getBeforeNodesInSameBranch = useCallback((nodeId: string, newNodes?: Node[], newEdges?: Edge[]) => {
|
||||||
const {
|
const { nodes: oldNodes, edges } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
const nodes = newNodes || oldNodes
|
||||||
edges,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = newNodes || getNodes()
|
|
||||||
const currentNode = nodes.find(node => node.id === nodeId)
|
const currentNode = nodes.find(node => node.id === nodeId)
|
||||||
|
|
||||||
const list: Node[] = []
|
const list: Node[] = []
|
||||||
@ -167,14 +157,11 @@ export const useWorkflow = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const getBeforeNodesInSameBranchIncludeParent = useCallback((nodeId: string, newNodes?: Node[], newEdges?: Edge[]) => {
|
const getBeforeNodesInSameBranchIncludeParent = useCallback((nodeId: string, newNodes?: Node[], newEdges?: Edge[]) => {
|
||||||
const nodes = getBeforeNodesInSameBranch(nodeId, newNodes, newEdges)
|
const nodes = getBeforeNodesInSameBranch(nodeId, newNodes, newEdges)
|
||||||
const {
|
const { nodes: allNodes } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
} = store.getState()
|
|
||||||
const allNodes = getNodes()
|
|
||||||
const node = allNodes.find(n => n.id === nodeId)
|
const node = allNodes.find(n => n.id === nodeId)
|
||||||
const parentNodeId = node?.parentId
|
const parentNodeId = node?.parentId
|
||||||
const parentNode = allNodes.find(n => n.id === parentNodeId)
|
const parentNode = allNodes.find(n => n.id === parentNodeId)
|
||||||
@ -182,14 +169,10 @@ export const useWorkflow = () => {
|
|||||||
nodes.push(parentNode)
|
nodes.push(parentNode)
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
}, [getBeforeNodesInSameBranch, store])
|
}, [getBeforeNodesInSameBranch, collaborativeWorkflow])
|
||||||
|
|
||||||
const getAfterNodesInSameBranch = useCallback((nodeId: string) => {
|
const getAfterNodesInSameBranch = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes, edges } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
edges,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
const currentNode = nodes.find(node => node.id === nodeId)!
|
const currentNode = nodes.find(node => node.id === nodeId)!
|
||||||
|
|
||||||
if (!currentNode)
|
if (!currentNode)
|
||||||
@ -213,40 +196,29 @@ export const useWorkflow = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return uniqBy(list, 'id')
|
return uniqBy(list, 'id')
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const getBeforeNodeById = useCallback((nodeId: string) => {
|
const getBeforeNodeById = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes, edges } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
edges,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
const node = nodes.find(node => node.id === nodeId)!
|
const node = nodes.find(node => node.id === nodeId)!
|
||||||
|
|
||||||
return getIncomers(node, nodes, edges)
|
return getIncomers(node, nodes, edges)
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const getIterationNodeChildren = useCallback((nodeId: string) => {
|
const getIterationNodeChildren = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
|
|
||||||
return nodes.filter(node => node.parentId === nodeId)
|
return nodes.filter(node => node.parentId === nodeId)
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const getLoopNodeChildren = useCallback((nodeId: string) => {
|
const getLoopNodeChildren = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
|
|
||||||
return nodes.filter(node => node.parentId === nodeId)
|
return nodes.filter(node => node.parentId === nodeId)
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const handleOutVarRenameChange = useCallback((nodeId: string, oldValeSelector: ValueSelector, newVarSelector: ValueSelector) => {
|
const handleOutVarRenameChange = useCallback((nodeId: string, oldValeSelector: ValueSelector, newVarSelector: ValueSelector) => {
|
||||||
const { getNodes, setNodes } = store.getState()
|
const { nodes: allNodes, setNodes } = collaborativeWorkflow.getState()
|
||||||
const allNodes = getNodes()
|
|
||||||
const affectedNodes = findUsedVarNodes(oldValeSelector, allNodes)
|
const affectedNodes = findUsedVarNodes(oldValeSelector, allNodes)
|
||||||
if (affectedNodes.length > 0) {
|
if (affectedNodes.length > 0) {
|
||||||
const newNodes = allNodes.map((node) => {
|
const newNodes = allNodes.map((node) => {
|
||||||
@ -257,7 +229,7 @@ export const useWorkflow = () => {
|
|||||||
})
|
})
|
||||||
setNodes(newNodes)
|
setNodes(newNodes)
|
||||||
}
|
}
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const isVarUsedInNodes = useCallback((varSelector: ValueSelector) => {
|
const isVarUsedInNodes = useCallback((varSelector: ValueSelector) => {
|
||||||
const nodeId = varSelector[0]
|
const nodeId = varSelector[0]
|
||||||
@ -268,11 +240,11 @@ export const useWorkflow = () => {
|
|||||||
|
|
||||||
const removeUsedVarInNodes = useCallback((varSelector: ValueSelector) => {
|
const removeUsedVarInNodes = useCallback((varSelector: ValueSelector) => {
|
||||||
const nodeId = varSelector[0]
|
const nodeId = varSelector[0]
|
||||||
const { getNodes, setNodes } = store.getState()
|
const { nodes, setNodes } = collaborativeWorkflow.getState()
|
||||||
const afterNodes = getAfterNodesInSameBranch(nodeId)
|
const afterNodes = getAfterNodesInSameBranch(nodeId)
|
||||||
const effectNodes = findUsedVarNodes(varSelector, afterNodes)
|
const effectNodes = findUsedVarNodes(varSelector, afterNodes)
|
||||||
if (effectNodes.length > 0) {
|
if (effectNodes.length > 0) {
|
||||||
const newNodes = getNodes().map((node) => {
|
const newNodes = nodes.map((node) => {
|
||||||
if (effectNodes.find(n => n.id === node.id))
|
if (effectNodes.find(n => n.id === node.id))
|
||||||
return updateNodeVars(node, varSelector, [])
|
return updateNodeVars(node, varSelector, [])
|
||||||
|
|
||||||
@ -280,7 +252,7 @@ export const useWorkflow = () => {
|
|||||||
})
|
})
|
||||||
setNodes(newNodes)
|
setNodes(newNodes)
|
||||||
}
|
}
|
||||||
}, [getAfterNodesInSameBranch, store])
|
}, [getAfterNodesInSameBranch, collaborativeWorkflow])
|
||||||
|
|
||||||
const isNodeVarsUsedInNodes = useCallback((node: Node, isChatMode: boolean) => {
|
const isNodeVarsUsedInNodes = useCallback((node: Node, isChatMode: boolean) => {
|
||||||
const outputVars = getNodeOutputVars(node, isChatMode)
|
const outputVars = getNodeOutputVars(node, isChatMode)
|
||||||
@ -291,9 +263,7 @@ export const useWorkflow = () => {
|
|||||||
}, [isVarUsedInNodes])
|
}, [isVarUsedInNodes])
|
||||||
|
|
||||||
const checkParallelLimit = useCallback((nodeId: string, nodeHandle = 'source') => {
|
const checkParallelLimit = useCallback((nodeId: string, nodeHandle = 'source') => {
|
||||||
const {
|
const { edges } = collaborativeWorkflow.getState()
|
||||||
edges,
|
|
||||||
} = store.getState()
|
|
||||||
const connectedEdges = edges.filter(edge => edge.source === nodeId && edge.sourceHandle === nodeHandle)
|
const connectedEdges = edges.filter(edge => edge.source === nodeId && edge.sourceHandle === nodeHandle)
|
||||||
if (connectedEdges.length > MAX_PARALLEL_LIMIT - 1) {
|
if (connectedEdges.length > MAX_PARALLEL_LIMIT - 1) {
|
||||||
const { setShowTips } = workflowStore.getState()
|
const { setShowTips } = workflowStore.getState()
|
||||||
@ -302,14 +272,10 @@ export const useWorkflow = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}, [store, workflowStore, t])
|
}, [collaborativeWorkflow, workflowStore, t])
|
||||||
|
|
||||||
const getRootNodesById = useCallback((nodeId: string) => {
|
const getRootNodesById = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes, edges } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
edges,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
const currentNode = nodes.find(node => node.id === nodeId)
|
const currentNode = nodes.find(node => node.id === nodeId)
|
||||||
|
|
||||||
const rootNodes: Node[] = []
|
const rootNodes: Node[] = []
|
||||||
@ -349,7 +315,7 @@ export const useWorkflow = () => {
|
|||||||
return uniqBy(rootNodes, 'id')
|
return uniqBy(rootNodes, 'id')
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const getStartNodes = useCallback((nodes: Node[], currentNode?: Node) => {
|
const getStartNodes = useCallback((nodes: Node[], currentNode?: Node) => {
|
||||||
const { id, parentId } = currentNode || {}
|
const { id, parentId } = currentNode || {}
|
||||||
@ -402,11 +368,7 @@ export const useWorkflow = () => {
|
|||||||
}, [t, workflowStore, getStartNodes])
|
}, [t, workflowStore, getStartNodes])
|
||||||
|
|
||||||
const isValidConnection = useCallback(({ source, sourceHandle, target }: Connection) => {
|
const isValidConnection = useCallback(({ source, sourceHandle, target }: Connection) => {
|
||||||
const {
|
const { nodes, edges } = collaborativeWorkflow.getState()
|
||||||
edges,
|
|
||||||
getNodes,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
const sourceNode: Node = nodes.find(node => node.id === source)!
|
const sourceNode: Node = nodes.find(node => node.id === source)!
|
||||||
const targetNode: Node = nodes.find(node => node.id === target)!
|
const targetNode: Node = nodes.find(node => node.id === target)!
|
||||||
|
|
||||||
@ -445,7 +407,7 @@ export const useWorkflow = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return !hasCycle(targetNode)
|
return !hasCycle(targetNode)
|
||||||
}, [store, checkParallelLimit, getAvailableBlocks])
|
}, [collaborativeWorkflow, checkParallelLimit, getAvailableBlocks])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getNodeById,
|
getNodeById,
|
||||||
@ -550,13 +512,10 @@ export const useNodesReadOnly = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useIsNodeInIteration = (iterationId: string) => {
|
export const useIsNodeInIteration = (iterationId: string) => {
|
||||||
const store = useStoreApi()
|
const collaborativeWorkflow = useCollaborativeWorkflow()
|
||||||
|
|
||||||
const isNodeInIteration = useCallback((nodeId: string) => {
|
const isNodeInIteration = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
const node = nodes.find(node => node.id === nodeId)
|
const node = nodes.find(node => node.id === nodeId)
|
||||||
|
|
||||||
if (!node)
|
if (!node)
|
||||||
@ -566,20 +525,17 @@ export const useIsNodeInIteration = (iterationId: string) => {
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}, [iterationId, store])
|
}, [iterationId, collaborativeWorkflow])
|
||||||
return {
|
return {
|
||||||
isNodeInIteration,
|
isNodeInIteration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useIsNodeInLoop = (loopId: string) => {
|
export const useIsNodeInLoop = (loopId: string) => {
|
||||||
const store = useStoreApi()
|
const collaborativeWorkflow = useCollaborativeWorkflow()
|
||||||
|
|
||||||
const isNodeInLoop = useCallback((nodeId: string) => {
|
const isNodeInLoop = useCallback((nodeId: string) => {
|
||||||
const {
|
const { nodes } = collaborativeWorkflow.getState()
|
||||||
getNodes,
|
|
||||||
} = store.getState()
|
|
||||||
const nodes = getNodes()
|
|
||||||
const node = nodes.find(node => node.id === nodeId)
|
const node = nodes.find(node => node.id === nodeId)
|
||||||
|
|
||||||
if (!node)
|
if (!node)
|
||||||
@ -589,7 +545,7 @@ export const useIsNodeInLoop = (loopId: string) => {
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}, [loopId, store])
|
}, [loopId, collaborativeWorkflow])
|
||||||
return {
|
return {
|
||||||
isNodeInLoop,
|
isNodeInLoop,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,6 @@ import {
|
|||||||
useCallback,
|
useCallback,
|
||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import {
|
|
||||||
useStoreApi,
|
|
||||||
} from 'reactflow'
|
|
||||||
import { RiBookOpenLine, RiCloseLine } from '@remixicon/react'
|
import { RiBookOpenLine, RiCloseLine } from '@remixicon/react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useStore } from '@/app/components/workflow/store'
|
import { useStore } from '@/app/components/workflow/store'
|
||||||
@ -25,15 +22,15 @@ import { useDocLink } from '@/context/i18n'
|
|||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud'
|
import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud'
|
||||||
import { updateConversationVariables } from '@/service/workflow'
|
import { updateConversationVariables } from '@/service/workflow'
|
||||||
|
import { useCollaborativeWorkflow } from '@/app/components/workflow/hooks/use-collaborative-workflow'
|
||||||
|
|
||||||
const ChatVariablePanel = () => {
|
const ChatVariablePanel = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const docLink = useDocLink()
|
const docLink = useDocLink()
|
||||||
const store = useStoreApi()
|
|
||||||
const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel)
|
const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel)
|
||||||
const varList = useStore(s => s.conversationVariables) as ConversationVariable[]
|
const varList = useStore(s => s.conversationVariables) as ConversationVariable[]
|
||||||
const updateChatVarList = useStore(s => s.setConversationVariables)
|
const updateChatVarList = useStore(s => s.setConversationVariables)
|
||||||
const appId = useStore(s => s.appId)
|
const appId = useStore(s => s.appId) as string
|
||||||
const {
|
const {
|
||||||
invalidateConversationVarValues,
|
invalidateConversationVarValues,
|
||||||
} = useInspectVarsCrud()
|
} = useInspectVarsCrud()
|
||||||
@ -44,27 +41,27 @@ const ChatVariablePanel = () => {
|
|||||||
|
|
||||||
const [showRemoveVarConfirm, setShowRemoveConfirm] = useState(false)
|
const [showRemoveVarConfirm, setShowRemoveConfirm] = useState(false)
|
||||||
const [cacheForDelete, setCacheForDelete] = useState<ConversationVariable>()
|
const [cacheForDelete, setCacheForDelete] = useState<ConversationVariable>()
|
||||||
|
const collaborativeWorkflow = useCollaborativeWorkflow()
|
||||||
|
|
||||||
const getEffectedNodes = useCallback((chatVar: ConversationVariable) => {
|
const getEffectedNodes = useCallback((chatVar: ConversationVariable) => {
|
||||||
const { getNodes } = store.getState()
|
const { nodes: allNodes } = collaborativeWorkflow.getState()
|
||||||
const allNodes = getNodes()
|
|
||||||
return findUsedVarNodes(
|
return findUsedVarNodes(
|
||||||
['conversation', chatVar.name],
|
['conversation', chatVar.name],
|
||||||
allNodes,
|
allNodes,
|
||||||
)
|
)
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const removeUsedVarInNodes = useCallback((chatVar: ConversationVariable) => {
|
const removeUsedVarInNodes = useCallback((chatVar: ConversationVariable) => {
|
||||||
const { getNodes, setNodes } = store.getState()
|
const { nodes, setNodes } = collaborativeWorkflow.getState()
|
||||||
const effectedNodes = getEffectedNodes(chatVar)
|
const effectedNodes = getEffectedNodes(chatVar)
|
||||||
const newNodes = getNodes().map((node) => {
|
const newNodes = nodes.map((node) => {
|
||||||
if (effectedNodes.find(n => n.id === node.id))
|
if (effectedNodes.find(n => n.id === node.id))
|
||||||
return updateNodeVars(node, ['conversation', chatVar.name], [])
|
return updateNodeVars(node, ['conversation', chatVar.name], [])
|
||||||
|
|
||||||
return node
|
return node
|
||||||
})
|
})
|
||||||
setNodes(newNodes)
|
setNodes(newNodes)
|
||||||
}, [getEffectedNodes, store])
|
}, [getEffectedNodes, collaborativeWorkflow])
|
||||||
|
|
||||||
const handleEdit = (chatVar: ConversationVariable) => {
|
const handleEdit = (chatVar: ConversationVariable) => {
|
||||||
setCurrentVar(chatVar)
|
setCurrentVar(chatVar)
|
||||||
@ -151,9 +148,9 @@ const ChatVariablePanel = () => {
|
|||||||
|
|
||||||
// side effects of rename conversation variable
|
// side effects of rename conversation variable
|
||||||
if (currentVar.name !== chatVar.name) {
|
if (currentVar.name !== chatVar.name) {
|
||||||
const { getNodes, setNodes } = store.getState()
|
const { nodes, setNodes } = collaborativeWorkflow.getState()
|
||||||
const effectedNodes = getEffectedNodes(currentVar)
|
const effectedNodes = getEffectedNodes(currentVar)
|
||||||
const newNodes = getNodes().map((node) => {
|
const newNodes = nodes.map((node) => {
|
||||||
if (effectedNodes.find(n => n.id === node.id))
|
if (effectedNodes.find(n => n.id === node.id))
|
||||||
return updateNodeVars(node, ['conversation', currentVar.name], ['conversation', chatVar.name])
|
return updateNodeVars(node, ['conversation', currentVar.name], ['conversation', chatVar.name])
|
||||||
|
|
||||||
@ -183,7 +180,7 @@ const ChatVariablePanel = () => {
|
|||||||
// Revert local state on error
|
// Revert local state on error
|
||||||
updateChatVarList(varList)
|
updateChatVarList(varList)
|
||||||
}
|
}
|
||||||
}, [currentVar, getEffectedNodes, store, updateChatVarList, varList, appId, invalidateConversationVarValues])
|
}, [currentVar, getEffectedNodes, collaborativeWorkflow, updateChatVarList, varList, appId, invalidateConversationVarValues])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -3,9 +3,6 @@ import {
|
|||||||
useCallback,
|
useCallback,
|
||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import {
|
|
||||||
useStoreApi,
|
|
||||||
} from 'reactflow'
|
|
||||||
import { RiCloseLine } from '@remixicon/react'
|
import { RiCloseLine } from '@remixicon/react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useStore } from '@/app/components/workflow/store'
|
import { useStore } from '@/app/components/workflow/store'
|
||||||
@ -20,16 +17,17 @@ import cn from '@/utils/classnames'
|
|||||||
import { webSocketClient } from '@/app/components/workflow/collaboration/core/websocket-manager'
|
import { webSocketClient } from '@/app/components/workflow/collaboration/core/websocket-manager'
|
||||||
import { useStore as useWorkflowStore } from '@/app/components/workflow/store'
|
import { useStore as useWorkflowStore } from '@/app/components/workflow/store'
|
||||||
import { updateEnvironmentVariables } from '@/service/workflow'
|
import { updateEnvironmentVariables } from '@/service/workflow'
|
||||||
|
import { useCollaborativeWorkflow } from '@/app/components/workflow/hooks/use-collaborative-workflow'
|
||||||
|
|
||||||
const EnvPanel = () => {
|
const EnvPanel = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const store = useStoreApi()
|
const collaborativeWorkflow = useCollaborativeWorkflow()
|
||||||
const setShowEnvPanel = useStore(s => s.setShowEnvPanel)
|
const setShowEnvPanel = useStore(s => s.setShowEnvPanel)
|
||||||
const envList = useStore(s => s.environmentVariables) as EnvironmentVariable[]
|
const envList = useStore(s => s.environmentVariables) as EnvironmentVariable[]
|
||||||
const envSecrets = useStore(s => s.envSecrets)
|
const envSecrets = useStore(s => s.envSecrets)
|
||||||
const updateEnvList = useStore(s => s.setEnvironmentVariables)
|
const updateEnvList = useStore(s => s.setEnvironmentVariables)
|
||||||
const setEnvSecrets = useStore(s => s.setEnvSecrets)
|
const setEnvSecrets = useStore(s => s.setEnvSecrets)
|
||||||
const appId = useWorkflowStore(s => s.appId)
|
const appId = useWorkflowStore(s => s.appId) as string
|
||||||
|
|
||||||
const [showVariableModal, setShowVariableModal] = useState(false)
|
const [showVariableModal, setShowVariableModal] = useState(false)
|
||||||
const [currentVar, setCurrentVar] = useState<EnvironmentVariable>()
|
const [currentVar, setCurrentVar] = useState<EnvironmentVariable>()
|
||||||
@ -42,25 +40,24 @@ const EnvPanel = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getEffectedNodes = useCallback((env: EnvironmentVariable) => {
|
const getEffectedNodes = useCallback((env: EnvironmentVariable) => {
|
||||||
const { getNodes } = store.getState()
|
const { nodes: allNodes } = collaborativeWorkflow.getState()
|
||||||
const allNodes = getNodes()
|
|
||||||
return findUsedVarNodes(
|
return findUsedVarNodes(
|
||||||
['env', env.name],
|
['env', env.name],
|
||||||
allNodes,
|
allNodes,
|
||||||
)
|
)
|
||||||
}, [store])
|
}, [collaborativeWorkflow])
|
||||||
|
|
||||||
const removeUsedVarInNodes = useCallback((env: EnvironmentVariable) => {
|
const removeUsedVarInNodes = useCallback((env: EnvironmentVariable) => {
|
||||||
const { getNodes, setNodes } = store.getState()
|
const { nodes, setNodes } = collaborativeWorkflow.getState()
|
||||||
const effectedNodes = getEffectedNodes(env)
|
const effectedNodes = getEffectedNodes(env)
|
||||||
const newNodes = getNodes().map((node) => {
|
const newNodes = nodes.map((node) => {
|
||||||
if (effectedNodes.find(n => n.id === node.id))
|
if (effectedNodes.find(n => n.id === node.id))
|
||||||
return updateNodeVars(node, ['env', env.name], [])
|
return updateNodeVars(node, ['env', env.name], [])
|
||||||
|
|
||||||
return node
|
return node
|
||||||
})
|
})
|
||||||
setNodes(newNodes)
|
setNodes(newNodes)
|
||||||
}, [getEffectedNodes, store])
|
}, [getEffectedNodes, collaborativeWorkflow])
|
||||||
|
|
||||||
const handleEdit = (env: EnvironmentVariable) => {
|
const handleEdit = (env: EnvironmentVariable) => {
|
||||||
setCurrentVar(env)
|
setCurrentVar(env)
|
||||||
@ -185,9 +182,9 @@ const EnvPanel = () => {
|
|||||||
|
|
||||||
// side effects of rename env
|
// side effects of rename env
|
||||||
if (currentVar.name !== env.name) {
|
if (currentVar.name !== env.name) {
|
||||||
const { getNodes, setNodes } = store.getState()
|
const { nodes, setNodes } = collaborativeWorkflow.getState()
|
||||||
const effectedNodes = getEffectedNodes(currentVar)
|
const effectedNodes = getEffectedNodes(currentVar)
|
||||||
const newNodes = getNodes().map((node) => {
|
const newNodes = nodes.map((node) => {
|
||||||
if (effectedNodes.find(n => n.id === node.id))
|
if (effectedNodes.find(n => n.id === node.id))
|
||||||
return updateNodeVars(node, ['env', currentVar.name], ['env', env.name])
|
return updateNodeVars(node, ['env', currentVar.name], ['env', env.name])
|
||||||
|
|
||||||
@ -218,7 +215,7 @@ const EnvPanel = () => {
|
|||||||
// Revert local state on error
|
// Revert local state on error
|
||||||
updateEnvList(envList)
|
updateEnvList(envList)
|
||||||
}
|
}
|
||||||
}, [currentVar, envList, envSecrets, getEffectedNodes, setEnvSecrets, store, updateEnvList, appId])
|
}, [currentVar, envList, envSecrets, getEffectedNodes, setEnvSecrets, collaborativeWorkflow, updateEnvList, appId])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useClickAway } from 'ahooks'
|
import { useClickAway } from 'ahooks'
|
||||||
import { useStore as useReactFlowStore, useStoreApi } from 'reactflow'
|
import { useStore as useReactFlowStore } from 'reactflow'
|
||||||
import {
|
import {
|
||||||
RiAlignBottom,
|
RiAlignBottom,
|
||||||
RiAlignCenter,
|
RiAlignCenter,
|
||||||
@ -22,6 +22,7 @@ import { WorkflowHistoryEvent, useWorkflowHistory } from './hooks/use-workflow-h
|
|||||||
import { useStore } from './store'
|
import { useStore } from './store'
|
||||||
import { useSelectionInteractions } from './hooks/use-selection-interactions'
|
import { useSelectionInteractions } from './hooks/use-selection-interactions'
|
||||||
import { useWorkflowStore } from './store'
|
import { useWorkflowStore } from './store'
|
||||||
|
import { useCollaborativeWorkflow } from '@/app/components/workflow/hooks/use-collaborative-workflow'
|
||||||
|
|
||||||
enum AlignType {
|
enum AlignType {
|
||||||
Left = 'left',
|
Left = 'left',
|
||||||
@ -42,8 +43,8 @@ const SelectionContextmenu = () => {
|
|||||||
const selectionMenu = useStore(s => s.selectionMenu)
|
const selectionMenu = useStore(s => s.selectionMenu)
|
||||||
|
|
||||||
// Access React Flow methods
|
// Access React Flow methods
|
||||||
const store = useStoreApi()
|
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
|
const collaborativeWorkflow = useCollaborativeWorkflow()
|
||||||
|
|
||||||
// Get selected nodes for alignment logic
|
// Get selected nodes for alignment logic
|
||||||
const selectedNodes = useReactFlowStore(state =>
|
const selectedNodes = useReactFlowStore(state =>
|
||||||
@ -256,7 +257,7 @@ const SelectionContextmenu = () => {
|
|||||||
workflowStore.setState({ nodeAnimation: false })
|
workflowStore.setState({ nodeAnimation: false })
|
||||||
|
|
||||||
// Get all current nodes
|
// Get all current nodes
|
||||||
const nodes = store.getState().getNodes()
|
const { nodes, setNodes } = collaborativeWorkflow.getState()
|
||||||
|
|
||||||
// Get all selected nodes
|
// Get all selected nodes
|
||||||
const selectedNodeIds = selectedNodes.map(node => node.id)
|
const selectedNodeIds = selectedNodes.map(node => node.id)
|
||||||
@ -312,7 +313,7 @@ const SelectionContextmenu = () => {
|
|||||||
const distributeNodes = handleDistributeNodes(nodesToAlign, nodes, alignType)
|
const distributeNodes = handleDistributeNodes(nodesToAlign, nodes, alignType)
|
||||||
if (distributeNodes) {
|
if (distributeNodes) {
|
||||||
// Apply node distribution updates
|
// Apply node distribution updates
|
||||||
store.getState().setNodes(distributeNodes)
|
setNodes(distributeNodes)
|
||||||
handleSelectionContextmenuCancel()
|
handleSelectionContextmenuCancel()
|
||||||
|
|
||||||
// Clear guide lines
|
// Clear guide lines
|
||||||
@ -347,7 +348,7 @@ const SelectionContextmenu = () => {
|
|||||||
// Apply node position updates - consistent with handleNodeDrag and handleNodeDragStop
|
// Apply node position updates - consistent with handleNodeDrag and handleNodeDragStop
|
||||||
try {
|
try {
|
||||||
// Directly use setNodes to update nodes - consistent with handleNodeDrag
|
// Directly use setNodes to update nodes - consistent with handleNodeDrag
|
||||||
store.getState().setNodes(newNodes)
|
setNodes(newNodes)
|
||||||
|
|
||||||
// Close popup
|
// Close popup
|
||||||
handleSelectionContextmenuCancel()
|
handleSelectionContextmenuCancel()
|
||||||
@ -366,7 +367,7 @@ const SelectionContextmenu = () => {
|
|||||||
catch (err) {
|
catch (err) {
|
||||||
console.error('Failed to update nodes:', err)
|
console.error('Failed to update nodes:', err)
|
||||||
}
|
}
|
||||||
}, [store, workflowStore, selectedNodes, getNodesReadOnly, handleSyncWorkflowDraft, saveStateToHistory, handleSelectionContextmenuCancel, handleAlignNode, handleDistributeNodes])
|
}, [collaborativeWorkflow, workflowStore, selectedNodes, getNodesReadOnly, handleSyncWorkflowDraft, saveStateToHistory, handleSelectionContextmenuCancel, handleAlignNode, handleDistributeNodes])
|
||||||
|
|
||||||
if (!selectionMenu)
|
if (!selectionMenu)
|
||||||
return null
|
return null
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user