Files
dify/web/app/components/workflow/node-actions-menu/use-node-actions-menu-model.ts
Joel ebe9836dca Merge remote-tracking branch 'origin/main' into feat/end-user-auth-fe
# Conflicts:
#	web/app/components/header/account-dropdown/__tests__/index.spec.tsx
#	web/app/components/plugins/plugin-auth/__tests__/plugin-auth.spec.tsx
#	web/app/components/plugins/plugin-auth/authorize/__tests__/add-oauth-button.spec.tsx
#	web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx
#	web/app/components/plugins/plugin-auth/authorize/__tests__/index.spec.tsx
#	web/app/components/plugins/plugin-auth/authorize/__tests__/oauth-client-settings.spec.tsx
#	web/app/components/plugins/plugin-auth/authorize/add-oauth-button.tsx
#	web/app/components/plugins/plugin-auth/authorize/api-key-modal.tsx
#	web/app/components/plugins/plugin-auth/authorize/oauth-client-settings.tsx
#	web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx
#	web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts
#	web/app/components/workflow/node-actions-menu/__tests__/index.spec.tsx
#	web/app/components/workflow/nodes/_base/components/__tests__/node-control.spec.tsx
#	web/app/components/workflow/nodes/_base/components/workflow-panel/__tests__/index.spec.tsx
#	web/app/components/workflow/nodes/_base/components/workflow-panel/index.tsx
#	web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/__tests__/index.spec.tsx
#	web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/__tests__/use-last-run.spec.ts
#	web/app/components/workflow/nodes/tool/__tests__/node.spec.tsx
#	web/app/components/workflow/nodes/tool/__tests__/panel.spec.tsx
#	web/app/components/workflow/utils/__tests__/node-navigation.spec.ts
#	web/app/components/workflow/utils/node-navigation.ts
2026-10-19 10:44:31 +08:00

117 lines
4.1 KiB
TypeScript

import type { Node } from '@/app/components/workflow/types'
import { useQuery } from '@tanstack/react-query'
import { useCallback, useMemo } from 'react'
import { useEdges } from 'reactflow'
import { CollectionType } from '@/app/components/tools/types'
import { selectToolsWithProvider } from '@/app/components/tools/utils/query-select'
import { useHooksStore } from '@/app/components/workflow/hooks-store'
import { useWorkflowStore } from '@/app/components/workflow/store'
import { BlockEnum, NodeRunningStatus } from '@/app/components/workflow/types'
import { canRunBySingle } from '@/app/components/workflow/utils'
import { consoleQuery } from '@/service/console'
import { matchesProviderReference } from '@/utils/provider-reference'
import { useNodesInteractions } from '../hooks/use-nodes-interactions'
import { useNodeMetaData } from '../hooks/use-nodes-meta-data'
import { useSingleRunAuthorization } from '../hooks/use-single-run-authorization'
import { useNodesReadOnly } from '../hooks/use-workflow'
type UseNodeActionsMenuModelParams = {
id: string
data: Node['data']
onClose: () => void
showHelpLink?: boolean
}
export function useNodeActionsMenuModel({
id,
data,
onClose,
showHelpLink = true,
}: UseNodeActionsMenuModelParams) {
const edges = useEdges()
const { handleNodeDelete, handleNodesDuplicate, handleNodeSelect, handleNodesCopy } =
useNodesInteractions()
const workflowStore = useWorkflowStore()
const { nodesReadOnly } = useNodesReadOnly()
const canRunWorkflow = useHooksStore((s) => s.accessControl.canRun)
const nodeMetaData = useNodeMetaData({ id, data } as Node)
const { data: workflowTools } = useQuery(
consoleQuery.workspaces.current.tools.workflow.get.queryOptions({
select: selectToolsWithProvider,
}),
)
const isChildNode = !!(data.isInIteration || data.isInLoop)
const canRun = canRunWorkflow && !nodesReadOnly && canRunBySingle(data.type, isChildNode)
const isSingleRunning = data._singleRunningStatus === NodeRunningStatus.Running
const { disabledReason } = useSingleRunAuthorization(id, data)
const singleRunDisabledReason = isSingleRunning ? undefined : disabledReason
const canChangeBlock = !nodeMetaData.isTypeFixed && !nodeMetaData.isUndeletable && !nodesReadOnly
const sourceHandle = useMemo(() => {
return edges.find((edge) => edge.target === id)?.sourceHandle || 'source'
}, [edges, id])
const workflowAppHref = useMemo(() => {
const isWorkflowTool =
data.type === BlockEnum.Tool && data.provider_type === CollectionType.workflow
if (!isWorkflowTool || !workflowTools || !data.provider_id) return undefined
const workflowTool = workflowTools.find((item) =>
matchesProviderReference(item, data.provider_id),
)
if (!workflowTool?.workflow_app_id) return undefined
return `/app/${workflowTool.workflow_app_id}/workflow`
}, [data.provider_id, data.provider_type, data.type, workflowTools])
const handleRun = useCallback(() => {
if (singleRunDisabledReason) return
const store = workflowStore.getState()
store.setInitShowLastRunTab(true)
store.setPendingSingleRun({
nodeId: id,
action: isSingleRunning ? 'stop' : 'run',
})
handleNodeSelect(id)
onClose()
}, [handleNodeSelect, id, isSingleRunning, onClose, workflowStore, singleRunDisabledReason])
const handleCopy = useCallback(() => {
onClose()
handleNodesCopy(id)
}, [handleNodesCopy, id, onClose])
const handleDuplicate = useCallback(() => {
onClose()
handleNodesDuplicate(id)
}, [handleNodesDuplicate, id, onClose])
const handleDelete = useCallback(() => {
onClose()
handleNodeDelete(id)
}, [handleNodeDelete, id, onClose])
return {
about: {
author: nodeMetaData.author,
description: nodeMetaData.description,
},
canChangeBlock,
canRun,
data,
handleCopy,
handleDelete,
handleDuplicate,
handleRun,
helpLinkUri: showHelpLink ? nodeMetaData.helpLinkUri : undefined,
id,
isSingleton: nodeMetaData.isSingleton,
isSingleRunning,
singleRunDisabledReason,
isUndeletable: nodeMetaData.isUndeletable,
nodesReadOnly,
sourceHandle,
workflowAppHref,
}
}