diff --git a/web/app/components/app/text-generate/item/index.tsx b/web/app/components/app/text-generate/item/index.tsx index 32cd6fee20..f201666311 100644 --- a/web/app/components/app/text-generate/item/index.tsx +++ b/web/app/components/app/text-generate/item/index.tsx @@ -27,9 +27,14 @@ import WorkflowProcessItem from '@/app/components/base/chat/chat/answer/workflow import type { WorkflowProcess } from '@/app/components/base/chat/types' const MAX_DEPTH = 3 +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export interface WorkflowProcessData extends WorkflowProcess { + expand: boolean +} + export type IGenerationItemProps = { isWorkflow?: boolean - workflowProcessData?: WorkflowProcess + workflowProcessData?: WorkflowProcessData className?: string isError: boolean onRetry: () => void @@ -285,7 +290,7 @@ const GenerationItem: FC = ({
{workflowProcessData && ( - + )} {isError ?
{t('share.generation.batchFailed.outputPlaceholder')}
diff --git a/web/app/components/base/chat/chat/answer/workflow-process.tsx b/web/app/components/base/chat/chat/answer/workflow-process.tsx index e24ea67110..d83009cea5 100644 --- a/web/app/components/base/chat/chat/answer/workflow-process.tsx +++ b/web/app/components/base/chat/chat/answer/workflow-process.tsx @@ -1,4 +1,5 @@ import { + useEffect, useMemo, useState, } from 'react' @@ -14,13 +15,15 @@ import NodePanel from '@/app/components/workflow/run/node' type WorkflowProcessProps = { data: WorkflowProcess grayBg?: boolean + expand?: boolean } const WorkflowProcessItem = ({ data, grayBg, + expand = false, }: WorkflowProcessProps) => { const { t } = useTranslation() - const [collapse, setCollapse] = useState(true) + const [collapse, setCollapse] = useState(!expand) const running = data.status === WorkflowRunningStatus.Running const succeeded = data.status === WorkflowRunningStatus.Succeeded const failed = data.status === WorkflowRunningStatus.Failed || data.status === WorkflowRunningStatus.Stopped @@ -36,12 +39,16 @@ const WorkflowProcessItem = ({ return 'linear-gradient(180deg, #FEE4E2 0%, #FEF3F2 100%)' }, [running, succeeded, failed, collapse]) + useEffect(() => { + setCollapse(!expand) + }, [expand]) + return (
= ({ doSetCompletionRes(res) } const getCompletionRes = () => completionResRef.current - const [workflowProcessData, doSetWorkflowProccessData] = useState() - const workflowProcessDataRef = useRef() - const setWorkflowProccessData = (data: WorkflowProcess) => { + const [workflowProcessData, doSetWorkflowProccessData] = useState() + const workflowProcessDataRef = useRef() + const setWorkflowProccessData = (data: WorkflowProcessData) => { workflowProcessDataRef.current = data doSetWorkflowProccessData(data) } @@ -191,7 +190,6 @@ const Result: FC = ({ }, 1000) if (isWorkflow) { - // ###TODO### let outputsExisted = false sendWorkflowMessage( data, @@ -201,33 +199,36 @@ const Result: FC = ({ setWorkflowProccessData({ status: WorkflowRunningStatus.Running, tracing: [], + expand: false, }) setRespondingFalse() - // console.log('onWorkflowStarted runID: ', workflow_run_id) }, onNodeStarted: ({ data }) => { setWorkflowProccessData(produce(getWorkflowProccessData()!, (draft) => { + draft.expand = true draft.tracing!.push({ ...data, status: NodeRunningStatus.Running, + expand: true, } as any) })) - // console.log('onNodeStarted: ', data.node_type) }, onNodeFinished: ({ data }) => { setWorkflowProccessData(produce(getWorkflowProccessData()!, (draft) => { const currentIndex = draft.tracing!.findIndex(trace => trace.node_id === data.node_id) - if (currentIndex > -1 && draft.tracing) - draft.tracing[currentIndex] = data as any + if (currentIndex > -1 && draft.tracing) { + draft.tracing[currentIndex] = { + ...data, + expand: !!data.error, + } as any + } })) - // console.log('onNodeFinished: ', data.node_type, data) if (data.node_type === BlockEnum.LLM && data.outputs.text) setCompletionRes(data.outputs.text) if (data.node_type === BlockEnum.End && data.outputs) outputsExisted = true }, onWorkflowFinished: ({ data }) => { - // console.log('onWorkflowFinished: ', data) if (isTimeout) return if (data.error) { @@ -324,14 +325,14 @@ const Result: FC = ({ return (
{!isCallBatchAPI && ( - (isResponding && !completionRes) + (isResponding && (!completionRes || !isWorkflow)) ? (
) : ( <> - {isNoData + {(isNoData && !workflowProcessData) ? : renderTextGenerationRes() } diff --git a/web/app/components/workflow/run/node.tsx b/web/app/components/workflow/run/node.tsx index a63f9f93e7..49a2ff4641 100644 --- a/web/app/components/workflow/run/node.tsx +++ b/web/app/components/workflow/run/node.tsx @@ -1,7 +1,7 @@ 'use client' import { useTranslation } from 'react-i18next' import type { FC } from 'react' -import { useState } from 'react' +import { useEffect, useState } from 'react' import cn from 'classnames' import BlockIcon from '../block-icon' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' @@ -13,12 +13,11 @@ import type { NodeTracing } from '@/types/workflow' type Props = { nodeInfo: NodeTracing - collapsed?: boolean className?: string } -const NodePanel: FC = ({ nodeInfo, collapsed = true, className }) => { - const [collapseState, setCollapseState] = useState(collapsed) +const NodePanel: FC = ({ nodeInfo, className }) => { + const [collapseState, setCollapseState] = useState(true) const { t } = useTranslation() const getTime = (time: number) => { @@ -38,6 +37,10 @@ const NodePanel: FC = ({ nodeInfo, collapsed = true, className }) => { return `${parseFloat((tokens / 1000000).toFixed(3))}M` } + useEffect(() => { + setCollapseState(!nodeInfo.expand) + }, [nodeInfo.expand]) + return (