import React, { useCallback, useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' import { useWorkflowRun, useWorkflowRunValidation, useWorkflowStartRun } from '@/app/components/workflow/hooks' import { useStore } from '@/app/components/workflow/store' import { WorkflowRunningStatus } from '@/app/components/workflow/types' import { useEventEmitterContextContext } from '@/context/event-emitter' import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types' import { getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils' import cn from '@/utils/classnames' import { RiLoader2Line, RiPlayLargeLine } from '@remixicon/react' import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' import { useDynamicTestRunOptions } from '../hooks/use-dynamic-test-run-options' import TestRunMenu, { type TestRunMenuRef, type TriggerOption, TriggerType } from './test-run-menu' import { useToastContext } from '@/app/components/base/toast' type RunModeProps = { text?: string } const RunMode = ({ text, }: RunModeProps) => { const { t } = useTranslation() const { handleWorkflowStartRunInWorkflow, handleWorkflowTriggerScheduleRunInWorkflow, handleWorkflowTriggerWebhookRunInWorkflow, handleWorkflowTriggerPluginRunInWorkflow, handleWorkflowRunAllTriggersInWorkflow, } = useWorkflowStartRun() const { handleStopRun } = useWorkflowRun() const { validateBeforeRun, warningNodes } = useWorkflowRunValidation() const workflowRunningData = useStore(s => s.workflowRunningData) const isListening = useStore(s => s.isListening) const status = workflowRunningData?.result.status const isRunning = status === WorkflowRunningStatus.Running || isListening const dynamicOptions = useDynamicTestRunOptions() const testRunMenuRef = useRef(null) const { notify } = useToastContext() useEffect(() => { // @ts-expect-error - Dynamic property for backward compatibility with keyboard shortcuts window._toggleTestRunDropdown = () => { testRunMenuRef.current?.toggle() } return () => { // @ts-expect-error - Dynamic property cleanup delete window._toggleTestRunDropdown } }, []) const handleStop = useCallback(() => { handleStopRun(workflowRunningData?.task_id || '') }, [handleStopRun, workflowRunningData?.task_id]) const handleTriggerSelect = useCallback((option: TriggerOption) => { // Validate checklist before running any workflow let isValid: boolean = true warningNodes.forEach((node) => { if (node.id === option.nodeId) isValid = false }) if (!isValid) { notify({ type: 'error', message: t('workflow.panel.checklistTip') }) return } if (option.type === TriggerType.UserInput) { handleWorkflowStartRunInWorkflow() } else if (option.type === TriggerType.Schedule) { handleWorkflowTriggerScheduleRunInWorkflow(option.nodeId) } else if (option.type === TriggerType.Webhook) { if (option.nodeId) handleWorkflowTriggerWebhookRunInWorkflow({ nodeId: option.nodeId }) } else if (option.type === TriggerType.Plugin) { if (option.nodeId) handleWorkflowTriggerPluginRunInWorkflow(option.nodeId) } else if (option.type === TriggerType.All) { const targetNodeIds = option.relatedNodeIds?.filter(Boolean) if (targetNodeIds && targetNodeIds.length > 0) handleWorkflowRunAllTriggersInWorkflow(targetNodeIds) } else { // Placeholder for trigger-specific execution logic for schedule, webhook, plugin types console.log('TODO: Handle trigger execution for type:', option.type, 'nodeId:', option.nodeId) } }, [ validateBeforeRun, handleWorkflowStartRunInWorkflow, handleWorkflowTriggerScheduleRunInWorkflow, handleWorkflowTriggerWebhookRunInWorkflow, handleWorkflowTriggerPluginRunInWorkflow, handleWorkflowRunAllTriggersInWorkflow, ]) const { eventEmitter } = useEventEmitterContextContext() eventEmitter?.useSubscription((v: any) => { if (v.type === EVENT_WORKFLOW_STOP) handleStop() }) return (
{ isRunning ? ( ) : (
{text ?? t('workflow.common.run')}
{getKeyboardKeyNameBySystem('alt')}
R
) } { isRunning && ( ) }
) } export default React.memo(RunMode)