mirror of https://github.com/langgenius/dify.git
available nodes
This commit is contained in:
parent
5adf94bd7d
commit
2203d9a138
|
|
@ -255,7 +255,7 @@ export const RETRIEVAL_OUTPUT_STRUCT = `{
|
|||
|
||||
export const SUPPORT_OUTPUT_VARS_NODE = [
|
||||
BlockEnum.Start, BlockEnum.LLM, BlockEnum.KnowledgeRetrieval, BlockEnum.Code, BlockEnum.TemplateTransform,
|
||||
BlockEnum.QuestionClassifier, BlockEnum.HttpRequest, BlockEnum.Tool, BlockEnum.VariableAssigner,
|
||||
BlockEnum.HttpRequest, BlockEnum.Tool, BlockEnum.VariableAssigner,
|
||||
]
|
||||
|
||||
const USAGE = {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import { useCallback, useRef } from 'react'
|
||||
import produce from 'immer'
|
||||
import type {
|
||||
HandleType,
|
||||
NodeDragHandler,
|
||||
NodeMouseHandler,
|
||||
OnConnect,
|
||||
OnConnectStart,
|
||||
} from 'reactflow'
|
||||
import {
|
||||
getConnectedEdges,
|
||||
|
|
@ -25,16 +27,21 @@ import {
|
|||
generateNewNode,
|
||||
getNodesConnectedSourceOrTargetHandleIdsMap,
|
||||
} from '../utils'
|
||||
import { useNodesInitialData } from './use-nodes-data'
|
||||
import {
|
||||
useNodesExtraData,
|
||||
useNodesInitialData,
|
||||
} from './use-nodes-data'
|
||||
import { useNodesSyncDraft } from './use-nodes-sync-draft'
|
||||
import { useWorkflow } from './use-workflow'
|
||||
|
||||
export const useNodesInteractions = () => {
|
||||
const store = useStoreApi()
|
||||
const nodesInitialData = useNodesInitialData()
|
||||
const nodesExtraData = useNodesExtraData()
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const { getAfterNodesInSameBranch } = useWorkflow()
|
||||
const dragNodeStartPosition = useRef({ x: 0, y: 0 } as { x: number; y: number })
|
||||
const connectingNodeRef = useRef<{ nodeId: string; handleType: HandleType } | null>(null)
|
||||
|
||||
const handleNodeDragStart = useCallback<NodeDragHandler>((_, node) => {
|
||||
const {
|
||||
|
|
@ -177,9 +184,27 @@ export const useNodesInteractions = () => {
|
|||
return
|
||||
|
||||
const {
|
||||
getNodes,
|
||||
setNodes,
|
||||
edges,
|
||||
setEdges,
|
||||
} = store.getState()
|
||||
const nodes = getNodes()
|
||||
|
||||
if (connectingNodeRef.current && connectingNodeRef.current.nodeId !== node.id) {
|
||||
const connectingNode: Node = nodes.find(n => n.id === connectingNodeRef.current!.nodeId)!
|
||||
const handleType = connectingNodeRef.current.handleType
|
||||
const currentNodeIndex = nodes.findIndex(n => n.id === node.id)
|
||||
const availablePrevNodes = nodesExtraData[connectingNode.data.type].availablePrevNodes
|
||||
const availableNextNodes = nodesExtraData[connectingNode.data.type].availableNextNodes
|
||||
const availableNodes = handleType === 'source' ? availableNextNodes : [...availablePrevNodes, BlockEnum.Start]
|
||||
|
||||
const newNodes = produce(nodes, (draft) => {
|
||||
if (!availableNodes.includes(draft[currentNodeIndex].data.type))
|
||||
draft[currentNodeIndex].data._isInvalidConnection = true
|
||||
})
|
||||
setNodes(newNodes)
|
||||
}
|
||||
const newEdges = produce(edges, (draft) => {
|
||||
const connectedEdges = getConnectedEdges([node], edges)
|
||||
|
||||
|
|
@ -190,7 +215,7 @@ export const useNodesInteractions = () => {
|
|||
})
|
||||
})
|
||||
setEdges(newEdges)
|
||||
}, [store])
|
||||
}, [store, nodesExtraData])
|
||||
|
||||
const handleNodeLeave = useCallback<NodeMouseHandler>(() => {
|
||||
const { runningStatus } = useStore.getState()
|
||||
|
|
@ -199,9 +224,17 @@ export const useNodesInteractions = () => {
|
|||
return
|
||||
|
||||
const {
|
||||
getNodes,
|
||||
setNodes,
|
||||
edges,
|
||||
setEdges,
|
||||
} = store.getState()
|
||||
const newNodes = produce(getNodes(), (draft) => {
|
||||
draft.forEach((node) => {
|
||||
node.data._isInvalidConnection = false
|
||||
})
|
||||
})
|
||||
setNodes(newNodes)
|
||||
const newEdges = produce(edges, (draft) => {
|
||||
draft.forEach((edge) => {
|
||||
edge.data = { ...edge.data, _connectedNodeIsHovering: false }
|
||||
|
|
@ -307,6 +340,19 @@ export const useNodesInteractions = () => {
|
|||
handleSyncWorkflowDraft()
|
||||
}, [store, handleSyncWorkflowDraft])
|
||||
|
||||
const handleNodeConnectStart = useCallback<OnConnectStart>((_, { nodeId, handleType }) => {
|
||||
if (nodeId && handleType) {
|
||||
connectingNodeRef.current = {
|
||||
nodeId,
|
||||
handleType,
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleNodeConnectEnd = useCallback(() => {
|
||||
connectingNodeRef.current = null
|
||||
}, [])
|
||||
|
||||
const handleNodeDelete = useCallback((nodeId: string) => {
|
||||
const { runningStatus } = useStore.getState()
|
||||
|
||||
|
|
@ -596,6 +642,8 @@ export const useNodesInteractions = () => {
|
|||
handleNodeSelect,
|
||||
handleNodeClick,
|
||||
handleNodeConnect,
|
||||
handleNodeConnectStart,
|
||||
handleNodeConnectEnd,
|
||||
handleNodeDelete,
|
||||
handleNodeChange,
|
||||
handleNodeAdd,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
getOutgoers,
|
||||
useStoreApi,
|
||||
} from 'reactflow'
|
||||
import type { Connection } from 'reactflow'
|
||||
import type { ToolsMap } from '../block-selector/types'
|
||||
import {
|
||||
generateNewNode,
|
||||
|
|
@ -21,7 +22,10 @@ import {
|
|||
START_INITIAL_POSITION,
|
||||
SUPPORT_OUTPUT_VARS_NODE,
|
||||
} from '../constants'
|
||||
import { useNodesInitialData } from './use-nodes-data'
|
||||
import {
|
||||
useNodesExtraData,
|
||||
useNodesInitialData,
|
||||
} from './use-nodes-data'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import {
|
||||
fetchNodesDefaultConfigs,
|
||||
|
|
@ -38,6 +42,7 @@ export const useIsChatMode = () => {
|
|||
|
||||
export const useWorkflow = () => {
|
||||
const store = useStoreApi()
|
||||
const nodesExtraData = useNodesExtraData()
|
||||
|
||||
const handleLayout = useCallback(async () => {
|
||||
const {
|
||||
|
|
@ -169,9 +174,24 @@ export const useWorkflow = () => {
|
|||
return list
|
||||
}, [store])
|
||||
|
||||
const isValidConnection = useCallback(() => {
|
||||
const isValidConnection = useCallback(({ source, target }: Connection) => {
|
||||
const { getNodes } = store.getState()
|
||||
const nodes = getNodes()
|
||||
const sourceNode: Node = nodes.find(node => node.id === source)!
|
||||
const targetNode: Node = nodes.find(node => node.id === target)!
|
||||
|
||||
if (sourceNode && targetNode) {
|
||||
const sourceNodeAvailableNextNodes = nodesExtraData[sourceNode.data.type].availableNextNodes
|
||||
const targetNodeAvailablePrevNodes = [...nodesExtraData[targetNode.data.type].availablePrevNodes, BlockEnum.Start]
|
||||
if (!sourceNodeAvailableNextNodes.includes(targetNode.data.type))
|
||||
return false
|
||||
|
||||
if (!targetNodeAvailablePrevNodes.includes(sourceNode.data.type))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}, [])
|
||||
}, [store, nodesExtraData])
|
||||
|
||||
return {
|
||||
handleLayout,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import ReactFlow, {
|
|||
Background,
|
||||
ReactFlowProvider,
|
||||
useOnViewportChange,
|
||||
useStoreApi,
|
||||
} from 'reactflow'
|
||||
import type { Viewport } from 'reactflow'
|
||||
import 'reactflow/dist/style.css'
|
||||
|
|
@ -62,7 +61,6 @@ const Workflow: FC<WorkflowProps> = memo(({
|
|||
const showFeaturesPanel = useStore(state => state.showFeaturesPanel)
|
||||
const runningStatus = useStore(s => s.runningStatus)
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const store = useStoreApi()
|
||||
|
||||
useEffect(() => {
|
||||
setAutoFreeze(false)
|
||||
|
|
@ -80,6 +78,8 @@ const Workflow: FC<WorkflowProps> = memo(({
|
|||
handleNodeLeave,
|
||||
handleNodeClick,
|
||||
handleNodeConnect,
|
||||
handleNodeConnectStart,
|
||||
handleNodeConnectEnd,
|
||||
} = useNodesInteractions()
|
||||
const {
|
||||
handleEdgeEnter,
|
||||
|
|
@ -108,6 +108,7 @@ const Workflow: FC<WorkflowProps> = memo(({
|
|||
}
|
||||
<HelpLine />
|
||||
<ReactFlow
|
||||
className='workflow-inner'
|
||||
nodeTypes={nodeTypes}
|
||||
edgeTypes={edgeTypes}
|
||||
nodes={nodes}
|
||||
|
|
@ -119,6 +120,8 @@ const Workflow: FC<WorkflowProps> = memo(({
|
|||
onNodeMouseLeave={handleNodeLeave}
|
||||
onNodeClick={handleNodeClick}
|
||||
onConnect={handleNodeConnect}
|
||||
onConnectStart={handleNodeConnectStart}
|
||||
onConnectEnd={handleNodeConnectEnd}
|
||||
onEdgeMouseEnter={handleEdgeEnter}
|
||||
onEdgeMouseLeave={handleEdgeLeave}
|
||||
onEdgesChange={handleEdgesChange}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export const NodeTargetHandle = memo(({
|
|||
onClick={handleHandleClick}
|
||||
>
|
||||
{
|
||||
!connected && isConnectable && (
|
||||
!connected && isConnectable && !data._isInvalidConnection && (
|
||||
<BlockSelector
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
|
|
@ -156,7 +156,7 @@ export const NodeSourceHandle = memo(({
|
|||
onClick={handleHandleClick}
|
||||
>
|
||||
{
|
||||
!connected && isConnectable && (
|
||||
!connected && isConnectable && !data._isInvalidConnection && (
|
||||
<BlockSelector
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ const BaseNode: FC<BaseNodeProps> = ({
|
|||
<div
|
||||
className={`
|
||||
flex border-[2px] rounded-2xl
|
||||
${(data.selected && !data._runningStatus) ? 'border-primary-600' : 'border-transparent'}
|
||||
${(data.selected && !data._runningStatus && !data._isInvalidConnection) ? 'border-primary-600' : 'border-transparent'}
|
||||
`}
|
||||
>
|
||||
<div
|
||||
|
|
@ -48,6 +48,7 @@ const BaseNode: FC<BaseNodeProps> = ({
|
|||
${data._runningStatus === NodeRunningStatus.Succeeded && '!border-[#12B76A]'}
|
||||
${data._runningStatus === NodeRunningStatus.Failed && '!border-[#F04438]'}
|
||||
${data._runningStatus === NodeRunningStatus.Waiting && 'opacity-70'}
|
||||
${data._isInvalidConnection && '!border-[#F04438]'}
|
||||
`}
|
||||
>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
.react-flow__node {
|
||||
transition: transform 0.1s ease-in-out;
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ export type Branch = {
|
|||
}
|
||||
|
||||
export type CommonNodeType<T = {}> = {
|
||||
_isInvalidConnection?: boolean
|
||||
_connectedSourceHandleIds?: string[]
|
||||
_connectedTargetHandleIds?: string[]
|
||||
_targetBranches?: Branch[]
|
||||
|
|
|
|||
Loading…
Reference in New Issue