diff --git a/web/app/components/workflow-app/hooks/use-workflow-run.ts b/web/app/components/workflow-app/hooks/use-workflow-run.ts index 9252718a53..8fd3b57ac6 100644 --- a/web/app/components/workflow-app/hooks/use-workflow-run.ts +++ b/web/app/components/workflow-app/hooks/use-workflow-run.ts @@ -220,13 +220,13 @@ export const useWorkflowRun = () => { if (runMode === 'webhook') { setWorkflowRunningData({ result: { - status: WorkflowRunningStatus.Waiting, + status: WorkflowRunningStatus.Listening, inputs_truncated: false, process_data_truncated: false, outputs_truncated: false, }, tracing: [], - resultText: 'Waiting for webhook call...', + resultText: 'Listening for webhook call...', }) } else { diff --git a/web/app/components/workflow/header/run-mode.tsx b/web/app/components/workflow/header/run-mode.tsx index 067be78dcf..682e0ff435 100644 --- a/web/app/components/workflow/header/run-mode.tsx +++ b/web/app/components/workflow/header/run-mode.tsx @@ -30,8 +30,8 @@ const RunMode = ({ const workflowRunningData = useStore(s => s.workflowRunningData) const status = workflowRunningData?.result.status - const isWaiting = status === WorkflowRunningStatus.Waiting - const isRunning = status === WorkflowRunningStatus.Running || isWaiting + const isListening = status === WorkflowRunningStatus.Listening + const isRunning = status === WorkflowRunningStatus.Running || isListening const dynamicOptions = useDynamicTestRunOptions() const testRunMenuRef = useRef(null) @@ -96,7 +96,7 @@ const RunMode = ({ disabled={true} > - {isWaiting ? t('workflow.common.waiting', { defaultValue: 'Waiting' }) : t('workflow.common.running')} + {isListening ? t('workflow.common.listening') : t('workflow.common.running')} ) : ( diff --git a/web/app/components/workflow/panel/record.tsx b/web/app/components/workflow/panel/record.tsx index e9c677d235..bea17e9013 100644 --- a/web/app/components/workflow/panel/record.tsx +++ b/web/app/components/workflow/panel/record.tsx @@ -5,9 +5,11 @@ import { useStore } from '../store' import { useWorkflowUpdate } from '../hooks' import { useHooksStore } from '../hooks-store' import { formatWorkflowRunIdentifier } from '../utils' +import { WorkflowRunningStatus } from '../types' const Record = () => { const historyWorkflowData = useStore(s => s.historyWorkflowData) + const workflowRunningData = useStore(s => s.workflowRunningData) const { handleUpdateWorkflowCanvas } = useWorkflowUpdate() const getWorkflowRunAndTraceUrl = useHooksStore(s => s.getWorkflowRunAndTraceUrl) @@ -20,6 +22,9 @@ const Record = () => { }) }, [handleUpdateWorkflowCanvas]) + const currentStatus = workflowRunningData?.result.status + const activeTab = currentStatus === WorkflowRunningStatus.Listening ? 'DETAIL' : undefined + return (
@@ -29,6 +34,8 @@ const Record = () => { runDetailUrl={getWorkflowRunAndTraceUrl(historyWorkflowData?.id).runUrl} tracingListUrl={getWorkflowRunAndTraceUrl(historyWorkflowData?.id).traceUrl} getResultCallback={handleResultCallback} + activeTab={activeTab} + statusHint={currentStatus} />
) diff --git a/web/app/components/workflow/panel/workflow-preview.tsx b/web/app/components/workflow/panel/workflow-preview.tsx index fdb1767df9..6b6ac4100c 100644 --- a/web/app/components/workflow/panel/workflow-preview.tsx +++ b/web/app/components/workflow/panel/workflow-preview.tsx @@ -48,7 +48,16 @@ const WorkflowPreview = () => { }, [showDebugAndPreviewPanel, showInputsPanel]) useEffect(() => { - if ((workflowRunningData?.result.status === WorkflowRunningStatus.Succeeded || workflowRunningData?.result.status === WorkflowRunningStatus.Failed) && !workflowRunningData.resultText && !workflowRunningData.result.files?.length) + const status = workflowRunningData?.result.status + if (!workflowRunningData) + return + + if (status === WorkflowRunningStatus.Listening) { + switchTab('DETAIL') + return + } + + if ((status === WorkflowRunningStatus.Succeeded || status === WorkflowRunningStatus.Failed) && !workflowRunningData.resultText && !workflowRunningData.result.files?.length) switchTab('DETAIL') }, [workflowRunningData]) diff --git a/web/app/components/workflow/run/index.tsx b/web/app/components/workflow/run/index.tsx index 2c5cc165c1..d9f226c52e 100644 --- a/web/app/components/workflow/run/index.tsx +++ b/web/app/components/workflow/run/index.tsx @@ -5,6 +5,7 @@ import { useContext } from 'use-context-selector' import { useTranslation } from 'react-i18next' import OutputPanel from './output-panel' import ResultPanel from './result-panel' +import StatusPanel from './status' import TracingPanel from './tracing-panel' import cn from '@/utils/classnames' import { ToastContext } from '@/app/components/base/toast' @@ -12,12 +13,14 @@ import Loading from '@/app/components/base/loading' import { fetchRunDetail, fetchTracingList } from '@/service/log' import type { NodeTracing } from '@/types/workflow' import type { WorkflowRunDetailResponse } from '@/models/log' +import { WorkflowRunningStatus } from '@/app/components/workflow/types' export type RunProps = { hideResult?: boolean activeTab?: 'RESULT' | 'DETAIL' | 'TRACING' getResultCallback?: (result: WorkflowRunDetailResponse) => void runDetailUrl: string tracingListUrl: string + statusHint?: string } const RunPanel: FC = ({ @@ -26,6 +29,7 @@ const RunPanel: FC = ({ getResultCallback, runDetailUrl, tracingListUrl, + statusHint, }) => { const { t } = useTranslation() const { notify } = useContext(ToastContext) @@ -92,6 +96,13 @@ const RunPanel: FC = ({ getData() }, [runDetailUrl, tracingListUrl]) + const derivedStatus = runDetail?.status ?? statusHint + + useEffect(() => { + if (derivedStatus === WorkflowRunningStatus.Listening && currentTab !== 'DETAIL') + setCurrentTab('DETAIL') + }, [currentTab, derivedStatus]) + const [height, setHeight] = useState(0) const ref = useRef(null) @@ -163,6 +174,11 @@ const RunPanel: FC = ({ exceptionCounts={runDetail.exceptions_count} /> )} + {!loading && currentTab === 'DETAIL' && !runDetail && derivedStatus === WorkflowRunningStatus.Listening && ( + + )} {!loading && currentTab === 'TRACING' && ( = ({ children, }) => { const { theme } = useTheme() + const isActive = status === 'running' || status === 'listening' + return (
= ({ status === 'exception' && 'border-[rgba(247,144,9,0.8)] bg-workflow-display-warning-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-warning.svg)] text-text-destructive', status === 'exception' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(247,144,9,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]', status === 'exception' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(247,144,9,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]', - status === 'running' && 'border-[rgba(11,165,236,0.8)] bg-workflow-display-normal-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-running.svg)] text-util-colors-blue-light-blue-light-600', - status === 'running' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(11,165,236,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]', - status === 'running' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(11,165,236,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]', + isActive && 'border-[rgba(11,165,236,0.8)] bg-workflow-display-normal-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-running.svg)] text-util-colors-blue-light-blue-light-600', + isActive && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(11,165,236,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]', + isActive && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(11,165,236,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]', )} >
= ({ }) => { const { t } = useTranslation() const docLink = useDocLink() + const isActive = status === WorkflowRunningStatus.Running || status === WorkflowRunningStatus.Listening return ( @@ -39,15 +41,21 @@ const StatusPanel: FC = ({ status === 'partial-succeeded' && 'text-util-colors-green-green-600', status === 'failed' && 'text-util-colors-red-red-600', status === 'stopped' && 'text-util-colors-warning-warning-600', - status === 'running' && 'text-util-colors-blue-light-blue-light-600', + isActive && 'text-util-colors-blue-light-blue-light-600', )} > - {status === 'running' && ( + {status === WorkflowRunningStatus.Running && ( <> Running )} + {status === WorkflowRunningStatus.Listening && ( + <> + + Listening + + )} {status === 'succeeded' && ( <> @@ -83,10 +91,10 @@ const StatusPanel: FC = ({
{t('runLog.resultPanel.time')}
- {status === 'running' && ( + {isActive && (
)} - {status !== 'running' && ( + {!isActive && ( {time ? `${time?.toFixed(3)}s` : '-'} )}
@@ -94,10 +102,10 @@ const StatusPanel: FC = ({
{t('runLog.resultPanel.tokens')}
- {status === 'running' && ( + {isActive && (
)} - {status !== 'running' && ( + {!isActive && ( {`${tokens || 0} Tokens`} )}
diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index 0478e6c7c6..f611e78344 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -349,6 +349,7 @@ export type NodeDefault = { export type OnSelectBlock = (type: BlockEnum, toolDefaultValue?: ToolDefaultValue | PluginDefaultValue | DataSourceDefaultValue) => void export enum WorkflowRunningStatus { + Listening = 'listening', Waiting = 'waiting', Running = 'running', Succeeded = 'succeeded', diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index d44a957701..e22c50c1b5 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -11,6 +11,7 @@ const translation = { publishUpdate: 'Publish Update', run: 'Test Run', running: 'Running', + listening: 'Listening', chooseStartNodeToRun: 'Choose the start node to run', runAllTriggers: 'Run all triggers', inRunMode: 'In Run Mode',