mirror of https://github.com/langgenius/dify.git
feat(workflow): enhance group node availability checks
- Updated `checkMakeGroupAvailability` to include a check for existing group nodes, preventing group creation if a group node is already selected. - Modified `useMakeGroupAvailability` and `useNodesInteractions` hooks to incorporate the new group node check, ensuring accurate group creation logic. - Adjusted UI rendering logic in the workflow panel to conditionally display elements based on node type, specifically for group nodes.
This commit is contained in:
parent
9012dced6a
commit
d92c476388
|
|
@ -2,6 +2,7 @@ import type { PredecessorHandle } from '../utils'
|
|||
import { useMemo } from 'react'
|
||||
import { useStore as useReactFlowStore } from 'reactflow'
|
||||
import { shallow } from 'zustand/shallow'
|
||||
import { BlockEnum } from '../types'
|
||||
import { getCommonPredecessorHandles } from '../utils'
|
||||
|
||||
export type MakeGroupAvailability = {
|
||||
|
|
@ -24,9 +25,9 @@ type MinimalEdge = {
|
|||
export const checkMakeGroupAvailability = (
|
||||
selectedNodeIds: string[],
|
||||
edges: MinimalEdge[],
|
||||
hasGroupNode = false,
|
||||
): MakeGroupAvailability => {
|
||||
// Make group requires selecting at least 2 nodes.
|
||||
if (selectedNodeIds.length <= 1) {
|
||||
if (selectedNodeIds.length <= 1 || hasGroupNode) {
|
||||
return {
|
||||
canMakeGroup: false,
|
||||
branchEntryNodeIds: [],
|
||||
|
|
@ -109,8 +110,6 @@ export const checkMakeGroupAvailability = (
|
|||
}
|
||||
|
||||
export const useMakeGroupAvailability = (selectedNodeIds: string[]): MakeGroupAvailability => {
|
||||
// Subscribe to the minimal edge state we need (source/sourceHandle/target) to avoid
|
||||
// snowball rerenders caused by subscribing to the entire `edges` objects.
|
||||
const edgeKeys = useReactFlowStore((state) => {
|
||||
const delimiter = '\u0000'
|
||||
const keys = state.edges.map(edge => `${edge.source}${delimiter}${edge.sourceHandle || 'source'}${delimiter}${edge.target}`)
|
||||
|
|
@ -118,8 +117,11 @@ export const useMakeGroupAvailability = (selectedNodeIds: string[]): MakeGroupAv
|
|||
return keys
|
||||
}, shallow)
|
||||
|
||||
const hasGroupNode = useReactFlowStore((state) => {
|
||||
return state.getNodes().some(node => node.selected && node.data.type === BlockEnum.Group)
|
||||
})
|
||||
|
||||
return useMemo(() => {
|
||||
// Reconstruct a minimal edge list from `edgeKeys` for downstream graph checks.
|
||||
const delimiter = '\u0000'
|
||||
const edges = edgeKeys.map((key) => {
|
||||
const [source, handleId, target] = key.split(delimiter)
|
||||
|
|
@ -131,6 +133,6 @@ export const useMakeGroupAvailability = (selectedNodeIds: string[]): MakeGroupAv
|
|||
}
|
||||
})
|
||||
|
||||
return checkMakeGroupAvailability(selectedNodeIds, edges)
|
||||
}, [edgeKeys, selectedNodeIds])
|
||||
return checkMakeGroupAvailability(selectedNodeIds, edges, hasGroupNode)
|
||||
}, [edgeKeys, selectedNodeIds, hasGroupNode])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2550,23 +2550,24 @@ export const useNodesInteractions = () => {
|
|||
return nodes.some(node => node.data._isBundled)
|
||||
}, [store])
|
||||
|
||||
// Check if the current box selection can be grouped
|
||||
const getCanMakeGroup = useCallback(() => {
|
||||
const { getNodes, edges } = store.getState()
|
||||
const nodes = getNodes()
|
||||
const bundledNodeIds = nodes.filter(node => node.data._isBundled).map(node => node.id)
|
||||
const bundledNodes = nodes.filter(node => node.data._isBundled)
|
||||
|
||||
if (bundledNodeIds.length <= 1)
|
||||
if (bundledNodes.length <= 1)
|
||||
return false
|
||||
|
||||
const bundledNodeIds = bundledNodes.map(node => node.id)
|
||||
const minimalEdges = edges.map(edge => ({
|
||||
id: edge.id,
|
||||
source: edge.source,
|
||||
sourceHandle: edge.sourceHandle || 'source',
|
||||
target: edge.target,
|
||||
}))
|
||||
const hasGroupNode = bundledNodes.some(node => node.data.type === BlockEnum.Group)
|
||||
|
||||
const { canMakeGroup } = checkMakeGroupAvailability(bundledNodeIds, minimalEdges)
|
||||
const { canMakeGroup } = checkMakeGroupAvailability(bundledNodeIds, minimalEdges, hasGroupNode)
|
||||
return canMakeGroup
|
||||
}, [store])
|
||||
|
||||
|
|
@ -2574,19 +2575,20 @@ export const useNodesInteractions = () => {
|
|||
const { getNodes, setNodes, edges, setEdges } = store.getState()
|
||||
const nodes = getNodes()
|
||||
const bundledNodes = nodes.filter(node => node.data._isBundled)
|
||||
const bundledNodeIds = bundledNodes.map(node => node.id)
|
||||
|
||||
if (bundledNodeIds.length <= 1)
|
||||
if (bundledNodes.length <= 1)
|
||||
return
|
||||
|
||||
const bundledNodeIds = bundledNodes.map(node => node.id)
|
||||
const minimalEdges = edges.map(edge => ({
|
||||
id: edge.id,
|
||||
source: edge.source,
|
||||
sourceHandle: edge.sourceHandle || 'source',
|
||||
target: edge.target,
|
||||
}))
|
||||
const hasGroupNode = bundledNodes.some(node => node.data.type === BlockEnum.Group)
|
||||
|
||||
const { canMakeGroup } = checkMakeGroupAvailability(bundledNodeIds, minimalEdges)
|
||||
const { canMakeGroup } = checkMakeGroupAvailability(bundledNodeIds, minimalEdges, hasGroupNode)
|
||||
if (!canMakeGroup)
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ const BasePanel: FC<BasePanelProps> = ({
|
|||
)
|
||||
}
|
||||
{
|
||||
!needsToolAuth && !currentDataSource && !currentTriggerPlugin && (
|
||||
!needsToolAuth && !currentDataSource && !currentTriggerPlugin && data.type !== BlockEnum.Group && (
|
||||
<div className="flex items-center justify-between pl-4 pr-3">
|
||||
<Tab
|
||||
value={tabType}
|
||||
|
|
@ -603,9 +603,9 @@ const BasePanel: FC<BasePanelProps> = ({
|
|||
</div>
|
||||
)
|
||||
}
|
||||
<Split />
|
||||
{data.type !== BlockEnum.Group && <Split />}
|
||||
</div>
|
||||
{tabType === TabType.settings && (
|
||||
{(tabType === TabType.settings || data.type === BlockEnum.Group) && (
|
||||
<div className="flex flex-1 flex-col overflow-y-auto">
|
||||
<div>
|
||||
{cloneElement(children as any, {
|
||||
|
|
|
|||
Loading…
Reference in New Issue