'use client' import type { FC } from 'react' import { cn } from '@langgenius/dify-ui/cn' import { StatusDot } from '@langgenius/dify-ui/status-dot' import { useMemo } from 'react' import { Trans, useTranslation } from 'react-i18next' import StatusContainer from '@/app/components/workflow/run/status-container' import { useDocLink } from '@/context/i18n' import { useWorkflowPausedDetails } from '@/service/use-log' type ResultProps = { status: string time?: number tokens?: number error?: string exceptionCounts?: number isListening?: boolean workflowRunId?: string onOpenTracingTab?: () => void } const StatusPanel: FC = ({ status, time, tokens, error, exceptionCounts, isListening = false, workflowRunId, onOpenTracingTab, }) => { const { t } = useTranslation() const docLink = useDocLink() const { data: pausedDetails } = useWorkflowPausedDetails({ workflowRunId: workflowRunId || '', enabled: status === 'paused', }) const pausedReasons = useMemo(() => { const reasons: string[] = [] if (!pausedDetails) return reasons const hasHumanInputNode = pausedDetails.paused_nodes.some( (node) => node.pause_type.type === 'human_input', ) if (hasHumanInputNode) { reasons.push(t(($) => $['nodes.humanInput.log.reasonContent'], { ns: 'workflow' })) } return reasons }, [pausedDetails, t]) const pausedInputURLs = useMemo(() => { const inputURLs: string[] = [] if (!pausedDetails) return inputURLs const { paused_nodes } = pausedDetails const hasHumanInputNode = paused_nodes.some((node) => node.pause_type.type === 'human_input') if (hasHumanInputNode) { paused_nodes.forEach((node) => { if (node.pause_type.type === 'human_input') { inputURLs.push(node.pause_type.backstage_input_url) } }) } return inputURLs }, [pausedDetails]) const partialSucceededTip = exceptionCounts ? ( $['nodes.common.errorHandle.partialSucceeded.tip']} ns="workflow" values={{ num: exceptionCounts }} components={{ tracingLink: onOpenTracingTab ? ( { e.preventDefault() onOpenTracingTab() }} /> ) : ( ), }} /> ) : null return (
{t(($) => $['resultPanel.status'], { ns: 'runLog' })}
{status === 'running' && ( <> {isListening ? 'Listening' : 'Running'} )} {status === 'succeeded' && ( <> SUCCESS )} {status === 'partial-succeeded' && ( <> PARTIAL SUCCESS )} {status === 'exception' && ( <> EXCEPTION )} {status === 'failed' && ( <> FAIL )} {status === 'stopped' && ( <> STOP )} {status === 'paused' && ( <> PENDING )}
{t(($) => $['resultPanel.time'], { ns: 'runLog' })}
{(status === 'running' || status === 'paused') && (
)} {status !== 'running' && status !== 'paused' && ( {time ? `${time?.toFixed(3)}s` : '-'} )}
{t(($) => $['resultPanel.tokens'], { ns: 'runLog' })}
{(status === 'running' || status === 'paused') && (
)} {status !== 'running' && status !== 'paused' && {`${tokens || 0} Tokens`}}
{status === 'failed' && error && ( <>
{error}
{!!exceptionCounts && ( <>
{partialSucceededTip}
)} )} {status === 'partial-succeeded' && !!exceptionCounts && ( <>
{partialSucceededTip}
)} {status === 'exception' && ( <>
)} {status === 'paused' && ( <>
{t(($) => $['nodes.humanInput.log.reason'], { ns: 'workflow' })}
{pausedReasons.length > 0 ? ( pausedReasons.map((reason) => (
{reason}
)) ) : (
)}
{pausedInputURLs.length > 0 && (
{t(($) => $['nodes.humanInput.log.backstageInputURL'], { ns: 'workflow' })}
{pausedInputURLs.map((url) => ( {url} ))}
)}
)} ) } export default StatusPanel