import { cn } from '@langgenius/dify-ui/cn'
import {
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuSeparator,
} from '@langgenius/dify-ui/context-menu'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { FlowType } from '@/types/common'
import {
useDSL,
useIsChatMode,
useNodesInteractions,
useWorkflowMoveMode,
useWorkflowStartRun,
} from './hooks'
import { useHooksStore } from './hooks-store'
import { TEST_RUN_MENU_HOTKEY } from './hotkeys'
import { isSnippetCanvas } from './nodes/_base/hooks/snippet-input-field-vars'
import AddBlock from './operator/add-block'
import { useOperator } from './operator/hooks'
import { ShortcutKbd } from './shortcuts/shortcut-kbd'
import { useStore } from './store'
import { WorkflowRunningStatus } from './types'
export function PanelContextmenu({ onClose }: { onClose: () => void }) {
const { t } = useTranslation()
const isPanelContextMenu = useStore((s) => s.contextMenuTarget?.type === 'panel')
const clipboardElements = useStore((s) => s.clipboardElements)
const setShowImportDSLModal = useStore((s) => s.setShowImportDSLModal)
const pendingComment = useStore((s) => s.pendingComment)
const setCommentPlacing = useStore((s) => s.setCommentPlacing)
const setCommentQuickAdd = useStore((s) => s.setCommentQuickAdd)
const workflowRunningData = useStore((s) => s.workflowRunningData)
const historyWorkflowData = useStore((s) => s.historyWorkflowData)
const isRestoring = useStore((s) => s.isRestoring)
const { handleNodesPaste } = useNodesInteractions()
const { handleStartWorkflowRun, handleWorkflowStartRunInChatflow } = useWorkflowStartRun()
const { handleAddNote } = useOperator()
const { isCommentModeAvailable } = useWorkflowMoveMode()
const { exportCheck } = useDSL()
const accessControl = useHooksStore((s) => s.accessControl)
const flowType = useHooksStore((s) => s.configsMap?.flowType)
const isChatMode = useIsChatMode()
const workflowOperationReadOnly = !!(
workflowRunningData?.result.status === WorkflowRunningStatus.Running ||
workflowRunningData?.result.status === WorkflowRunningStatus.Paused ||
historyWorkflowData ||
isRestoring
)
const canEditWorkflow = accessControl.canEdit && !workflowOperationReadOnly
const shouldHideImportApp = flowType === FlowType.snippet || isSnippetCanvas()
const renderAddBlockTrigger = useCallback(() => {
return (
}
className={cn(
'w-[calc(100%-8px)]',
'justify-between gap-4 border-0 bg-transparent px-3 text-left text-text-secondary',
)}
>
{t(($) => $['common.addBlock'], { ns: 'workflow' })}
)
}, [t])
const handleRunAction = useCallback(() => {
if (isChatMode) handleWorkflowStartRunInChatflow()
else handleStartWorkflowRun()
onClose()
}, [isChatMode, handleWorkflowStartRunInChatflow, handleStartWorkflowRun, onClose])
if (!isPanelContextMenu) return null
return (
{canEditWorkflow && (
)}
{canEditWorkflow && (
{
e.stopPropagation()
handleAddNote()
onClose()
}}
>
{t(($) => $['nodes.note.addNote'], { ns: 'workflow' })}
)}
{!workflowOperationReadOnly && isCommentModeAvailable && (
{
e.stopPropagation()
if (pendingComment) return
setCommentQuickAdd(true)
setCommentPlacing(true)
onClose()
}}
>
{t(($) => $['comments.actions.addComment'], { ns: 'workflow' })}
)}
{accessControl.canRun && (
{isChatMode
? t(($) => $['common.debugAndPreview'], { ns: 'workflow' })
: t(($) => $['common.run'], { ns: 'workflow' })}
{!isChatMode && }
)}
{canEditWorkflow && (
<>
{
if (clipboardElements.length) {
handleNodesPaste()
onClose()
}
}}
>
{t(($) => $['common.pasteHere'], { ns: 'workflow' })}
>
)}
{accessControl.canImportExportDSL && (
<>
exportCheck?.()}
>
{t(($) => $.export, { ns: 'app' })}
{!shouldHideImportApp && (
setShowImportDSLModal(true)}
>
{t(($) => $.importApp, { ns: 'app' })}
)}
>
)}
)
}