feat: introduce trigger functionality (#27644)

Signed-off-by: lyzno1 <yuanyouhuilyz@gmail.com>
Co-authored-by: Stream <Stream_2@qq.com>
Co-authored-by: lyzno1 <92089059+lyzno1@users.noreply.github.com>
Co-authored-by: zhsama <torvalds@linux.do>
Co-authored-by: Harry <xh001x@hotmail.com>
Co-authored-by: lyzno1 <yuanyouhuilyz@gmail.com>
Co-authored-by: yessenia <yessenia.contact@gmail.com>
Co-authored-by: hjlarry <hjlarry@163.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: WTW0313 <twwu@dify.ai>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Yeuoly
2025-11-12 17:59:37 +08:00
committed by GitHub
parent ca7794305b
commit b76e17b25d
785 changed files with 41186 additions and 3725 deletions

View File

@@ -16,9 +16,9 @@ import {
useReactFlow,
useStoreApi,
} from 'reactflow'
import type { DataSourceDefaultValue, ToolDefaultValue } from '../block-selector/types'
import type { PluginDefaultValue } from '../block-selector/types'
import type { Edge, Node, OnNodeAdd } from '../types'
import { BlockEnum } from '../types'
import { BlockEnum, isTriggerNode } from '../types'
import { useWorkflowStore } from '../store'
import {
CUSTOM_EDGE,
@@ -63,6 +63,15 @@ import type { RAGPipelineVariables } from '@/models/pipeline'
import useInspectVarsCrud from './use-inspect-vars-crud'
import { getNodeUsedVars } from '../nodes/_base/components/variable/utils'
// Entry node deletion restriction has been removed to allow empty workflows
// Entry node (Start/Trigger) wrapper offsets for alignment
// Must match the values in use-helpline.ts
const ENTRY_NODE_WRAPPER_OFFSET = {
x: 0,
y: 21, // Adjusted based on visual testing feedback
} as const
export const useNodesInteractions = () => {
const { t } = useTranslation()
const store = useStoreApi()
@@ -138,21 +147,51 @@ export const useNodesInteractions = () => {
const newNodes = produce(nodes, (draft) => {
const currentNode = draft.find(n => n.id === node.id)!
if (showVerticalHelpLineNodesLength > 0)
currentNode.position.x = showVerticalHelpLineNodes[0].position.x
else if (restrictPosition.x !== undefined)
currentNode.position.x = restrictPosition.x
else if (restrictLoopPosition.x !== undefined)
currentNode.position.x = restrictLoopPosition.x
else currentNode.position.x = node.position.x
// Check if current dragging node is an entry node
const isCurrentEntryNode = isTriggerNode(node.data.type as any) || node.data.type === BlockEnum.Start
if (showHorizontalHelpLineNodesLength > 0)
currentNode.position.y = showHorizontalHelpLineNodes[0].position.y
else if (restrictPosition.y !== undefined)
// X-axis alignment with offset consideration
if (showVerticalHelpLineNodesLength > 0) {
const targetNode = showVerticalHelpLineNodes[0]
const isTargetEntryNode = isTriggerNode(targetNode.data.type as any) || targetNode.data.type === BlockEnum.Start
// Calculate the wrapper position needed to align the inner nodes
// Target inner position = target.position + target.offset
// Current inner position should equal target inner position
// So: current.position + current.offset = target.position + target.offset
// Therefore: current.position = target.position + target.offset - current.offset
const targetOffset = isTargetEntryNode ? ENTRY_NODE_WRAPPER_OFFSET.x : 0
const currentOffset = isCurrentEntryNode ? ENTRY_NODE_WRAPPER_OFFSET.x : 0
currentNode.position.x = targetNode.position.x + targetOffset - currentOffset
}
else if (restrictPosition.x !== undefined) {
currentNode.position.x = restrictPosition.x
}
else if (restrictLoopPosition.x !== undefined) {
currentNode.position.x = restrictLoopPosition.x
}
else {
currentNode.position.x = node.position.x
}
// Y-axis alignment with offset consideration
if (showHorizontalHelpLineNodesLength > 0) {
const targetNode = showHorizontalHelpLineNodes[0]
const isTargetEntryNode = isTriggerNode(targetNode.data.type as any) || targetNode.data.type === BlockEnum.Start
const targetOffset = isTargetEntryNode ? ENTRY_NODE_WRAPPER_OFFSET.y : 0
const currentOffset = isCurrentEntryNode ? ENTRY_NODE_WRAPPER_OFFSET.y : 0
currentNode.position.y = targetNode.position.y + targetOffset - currentOffset
}
else if (restrictPosition.y !== undefined) {
currentNode.position.y = restrictPosition.y
else if (restrictLoopPosition.y !== undefined)
}
else if (restrictLoopPosition.y !== undefined) {
currentNode.position.y = restrictLoopPosition.y
else currentNode.position.y = node.position.y
}
else {
currentNode.position.y = node.position.y
}
})
setNodes(newNodes)
},
@@ -357,6 +396,7 @@ export const useNodesInteractions = () => {
if (node.type === CUSTOM_ITERATION_START_NODE) return
if (node.type === CUSTOM_LOOP_START_NODE) return
if (node.data.type === BlockEnum.DataSourceEmpty) return
if (node.data._pluginInstallLocked) return
handleNodeSelect(node.id)
},
[handleNodeSelect],
@@ -735,7 +775,7 @@ export const useNodesInteractions = () => {
nodeType,
sourceHandle = 'source',
targetHandle = 'target',
toolDefaultValue,
pluginDefaultValue,
},
{ prevNodeId, prevNodeSourceHandle, nextNodeId, nextNodeTargetHandle },
) => {
@@ -756,7 +796,7 @@ export const useNodesInteractions = () => {
nodesWithSameType.length > 0
? `${defaultValue.title} ${nodesWithSameType.length + 1}`
: defaultValue.title,
...toolDefaultValue,
...pluginDefaultValue,
selected: true,
_showAddVariablePopup:
(nodeType === BlockEnum.VariableAssigner
@@ -1286,7 +1326,7 @@ export const useNodesInteractions = () => {
currentNodeId: string,
nodeType: BlockEnum,
sourceHandle: string,
toolDefaultValue?: ToolDefaultValue | DataSourceDefaultValue,
pluginDefaultValue?: PluginDefaultValue,
) => {
if (getNodesReadOnly()) return
@@ -1310,7 +1350,7 @@ export const useNodesInteractions = () => {
nodesWithSameType.length > 0
? `${defaultValue.title} ${nodesWithSameType.length + 1}`
: defaultValue.title,
...toolDefaultValue,
...pluginDefaultValue,
_connectedSourceHandleIds: [],
_connectedTargetHandleIds: [],
selected: currentNode.data.selected,
@@ -1656,7 +1696,7 @@ export const useNodesInteractions = () => {
const nodes = getNodes()
const bundledNodes = nodes.filter(
node => node.data._isBundled && node.data.type !== BlockEnum.Start,
node => node.data._isBundled,
)
if (bundledNodes.length) {
@@ -1669,7 +1709,7 @@ export const useNodesInteractions = () => {
if (edgeSelected) return
const selectedNode = nodes.find(
node => node.data.selected && node.data.type !== BlockEnum.Start,
node => node.data.selected,
)
if (selectedNode) handleNodeDelete(selectedNode.id)