mirror of
https://github.com/langgenius/dify.git
synced 2026-05-13 08:57:28 +08:00
refactor run data fetching
This commit is contained in:
parent
0439276866
commit
d537efe97a
@ -1,10 +1,18 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React, { useState } from 'react'
|
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
|
import { useContext } from 'use-context-selector'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import cn from 'classnames'
|
import cn from 'classnames'
|
||||||
import Result from './result'
|
import produce from 'immer'
|
||||||
import Tracing from './tracing'
|
import ResultPanel from './result-panel'
|
||||||
|
import TracingPanel from './tracing-panel'
|
||||||
|
import { ToastContext } from '@/app/components/base/toast'
|
||||||
|
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 { useStore as useAppStore } from '@/app/components/app/store'
|
||||||
|
|
||||||
type RunProps = {
|
type RunProps = {
|
||||||
activeTab?: 'RESULT' | 'TRACING'
|
activeTab?: 'RESULT' | 'TRACING'
|
||||||
@ -13,7 +21,81 @@ type RunProps = {
|
|||||||
|
|
||||||
const RunPanel: FC<RunProps> = ({ activeTab = 'RESULT', runID }) => {
|
const RunPanel: FC<RunProps> = ({ activeTab = 'RESULT', runID }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { notify } = useContext(ToastContext)
|
||||||
const [currentTab, setCurrentTab] = useState<string>(activeTab)
|
const [currentTab, setCurrentTab] = useState<string>(activeTab)
|
||||||
|
const { appDetail } = useAppStore()
|
||||||
|
const [loading, setLoading] = useState<boolean>(true)
|
||||||
|
const [runDetail, setRunDetail] = useState<WorkflowRunDetailResponse>()
|
||||||
|
const [list, setList] = useState<NodeTracing[]>([])
|
||||||
|
const [collapseState, setCollapseState] = useState<boolean[]>([])
|
||||||
|
|
||||||
|
const executor = useMemo(() => {
|
||||||
|
if (runDetail?.created_by_role === 'account')
|
||||||
|
return runDetail.created_by_account?.name || ''
|
||||||
|
if (runDetail?.created_by_role === 'end_user')
|
||||||
|
return runDetail.created_by_end_user?.session_id || ''
|
||||||
|
return 'N/A'
|
||||||
|
}, [runDetail])
|
||||||
|
|
||||||
|
const collapseStateChange = (index: number) => {
|
||||||
|
const newCollapseState = produce(collapseState, (draft: boolean[]) => {
|
||||||
|
draft[index] = !draft[index]
|
||||||
|
})
|
||||||
|
setCollapseState(newCollapseState)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getResult = useCallback(async (appID: string, runID: string) => {
|
||||||
|
try {
|
||||||
|
const res = await fetchRunDetail({
|
||||||
|
appID,
|
||||||
|
runID,
|
||||||
|
})
|
||||||
|
setRunDetail(res)
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
notify({
|
||||||
|
type: 'error',
|
||||||
|
message: `${err}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [notify])
|
||||||
|
|
||||||
|
const getTracingList = useCallback(async (appID: string, runID: string) => {
|
||||||
|
try {
|
||||||
|
const { data: nodeList } = await fetchTracingList({
|
||||||
|
url: `/apps/${appID}/workflow-runs/${runID}/node-executions`,
|
||||||
|
})
|
||||||
|
const collapseState = nodeList.map(node => node.status === 'succeeded')
|
||||||
|
setList(nodeList.reverse())
|
||||||
|
setCollapseState(collapseState)
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
notify({
|
||||||
|
type: 'error',
|
||||||
|
message: `${err}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [notify])
|
||||||
|
|
||||||
|
const getData = async (appID: string, runID: string) => {
|
||||||
|
setLoading(true)
|
||||||
|
await getResult(appID, runID)
|
||||||
|
await getTracingList(appID, runID)
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const switchTab = async (tab: string) => {
|
||||||
|
setCurrentTab(tab)
|
||||||
|
if (tab === 'RESULT')
|
||||||
|
appDetail?.id && await getResult(appDetail.id, runID)
|
||||||
|
appDetail?.id && await getTracingList(appDetail.id, runID)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// fetch data
|
||||||
|
if (appDetail && runID)
|
||||||
|
getData(appDetail.id, runID)
|
||||||
|
}, [appDetail, runID])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='grow relative flex flex-col'>
|
<div className='grow relative flex flex-col'>
|
||||||
@ -24,20 +106,46 @@ const RunPanel: FC<RunProps> = ({ activeTab = 'RESULT', runID }) => {
|
|||||||
'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer',
|
'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer',
|
||||||
currentTab === 'RESULT' && '!border-[rgb(21,94,239)] text-gray-700',
|
currentTab === 'RESULT' && '!border-[rgb(21,94,239)] text-gray-700',
|
||||||
)}
|
)}
|
||||||
onClick={() => setCurrentTab('RESULT')}
|
onClick={() => switchTab('RESULT')}
|
||||||
>{t('runLog.result')}</div>
|
>{t('runLog.result')}</div>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer',
|
'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer',
|
||||||
currentTab === 'TRACING' && '!border-[rgb(21,94,239)] text-gray-700',
|
currentTab === 'TRACING' && '!border-[rgb(21,94,239)] text-gray-700',
|
||||||
)}
|
)}
|
||||||
onClick={() => setCurrentTab('TRACING')}
|
onClick={() => switchTab('TRACING')}
|
||||||
>{t('runLog.tracing')}</div>
|
>{t('runLog.tracing')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className='flex h-full items-center justify-center bg-white'>
|
||||||
|
<Loading />
|
||||||
|
</div>
|
||||||
{/* panel detal */}
|
{/* panel detal */}
|
||||||
<div className={cn('grow bg-white h-0 overflow-y-auto', currentTab === 'TRACING' && '!bg-gray-50')}>
|
<div className={cn('grow bg-white h-0 overflow-y-auto', currentTab === 'TRACING' && '!bg-gray-50')}>
|
||||||
{currentTab === 'RESULT' && <Result runID={runID} />}
|
{loading && (
|
||||||
{currentTab === 'TRACING' && <Tracing runID={runID} />}
|
<div className='flex h-full items-center justify-center bg-white'>
|
||||||
|
<Loading />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!loading && currentTab === 'RESULT' && runDetail && (
|
||||||
|
<ResultPanel
|
||||||
|
inputs={runDetail.inputs}
|
||||||
|
outputs={runDetail.outputs}
|
||||||
|
status={runDetail.status}
|
||||||
|
error={runDetail.error}
|
||||||
|
elapsed_time={runDetail.elapsed_time}
|
||||||
|
total_tokens={runDetail.total_tokens}
|
||||||
|
created_at={runDetail.created_at}
|
||||||
|
created_by={executor}
|
||||||
|
steps={runDetail.total_steps}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!loading && currentTab === 'TRACING' && (
|
||||||
|
<TracingPanel
|
||||||
|
list={list}
|
||||||
|
collapseState={collapseState}
|
||||||
|
collapseHandle={collapseStateChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,64 +0,0 @@
|
|||||||
'use client'
|
|
||||||
import type { FC } from 'react'
|
|
||||||
import React, { useEffect, useMemo, useState } from 'react'
|
|
||||||
import ResultPanel from './result-panel'
|
|
||||||
import Loading from '@/app/components/base/loading'
|
|
||||||
import { fetchRunDetail } from '@/service/log'
|
|
||||||
import type { WorkflowRunDetailResponse } from '@/models/log'
|
|
||||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
|
||||||
|
|
||||||
type ResultProps = {
|
|
||||||
runID: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const Result: FC<ResultProps> = ({ runID }) => {
|
|
||||||
const { appDetail } = useAppStore()
|
|
||||||
const [loading, setLoading] = useState<boolean>(true)
|
|
||||||
const [runDetail, setRunDetail] = useState<WorkflowRunDetailResponse>()
|
|
||||||
|
|
||||||
const executor = useMemo(() => {
|
|
||||||
if (runDetail?.created_by_role === 'account')
|
|
||||||
return runDetail.created_by_account?.name || ''
|
|
||||||
if (runDetail?.created_by_role === 'end_user')
|
|
||||||
return runDetail.created_by_end_user?.session_id || ''
|
|
||||||
return 'N/A'
|
|
||||||
}, [runDetail])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// fetch data
|
|
||||||
if (appDetail && runID) {
|
|
||||||
setLoading(true)
|
|
||||||
fetchRunDetail({
|
|
||||||
appID: appDetail?.id,
|
|
||||||
runID,
|
|
||||||
}).then((res: WorkflowRunDetailResponse) => {
|
|
||||||
setLoading(false)
|
|
||||||
setRunDetail(res)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [appDetail, runID])
|
|
||||||
|
|
||||||
if (loading || !runDetail) {
|
|
||||||
return (
|
|
||||||
<div className='flex h-full items-center justify-center bg-white'>
|
|
||||||
<Loading />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ResultPanel
|
|
||||||
inputs={runDetail.inputs}
|
|
||||||
outputs={runDetail.outputs}
|
|
||||||
status={runDetail.status}
|
|
||||||
error={runDetail.error}
|
|
||||||
elapsed_time={runDetail.elapsed_time}
|
|
||||||
total_tokens={runDetail.total_tokens}
|
|
||||||
created_at={runDetail.created_at}
|
|
||||||
created_by={executor}
|
|
||||||
steps={runDetail.total_steps}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Result
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
'use client'
|
|
||||||
import type { FC } from 'react'
|
|
||||||
import React, { useCallback, useEffect, useState } from 'react'
|
|
||||||
import { useContext } from 'use-context-selector'
|
|
||||||
import produce from 'immer'
|
|
||||||
import TracingPanel from './tracing-panel'
|
|
||||||
import Loading from '@/app/components/base/loading'
|
|
||||||
import { fetchTracingList } from '@/service/log'
|
|
||||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
|
||||||
import type { NodeTracing } from '@/types/workflow'
|
|
||||||
import { ToastContext } from '@/app/components/base/toast'
|
|
||||||
|
|
||||||
type TracingProps = {
|
|
||||||
runID: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const Tracing: FC<TracingProps> = ({ runID }) => {
|
|
||||||
const { notify } = useContext(ToastContext)
|
|
||||||
const { appDetail } = useAppStore()
|
|
||||||
const [loading, setLoading] = useState<boolean>(true)
|
|
||||||
const [list, setList] = useState<NodeTracing[]>([])
|
|
||||||
const [collapseState, setCollapseState] = useState<boolean[]>([])
|
|
||||||
|
|
||||||
const getTracingList = useCallback(async (appID: string, runID: string) => {
|
|
||||||
setLoading(true)
|
|
||||||
try {
|
|
||||||
const { data: nodeList } = await fetchTracingList({
|
|
||||||
url: `/apps/${appID}/workflow-runs/${runID}/node-executions`,
|
|
||||||
})
|
|
||||||
const collapseState = nodeList.map(node => node.status === 'succeeded')
|
|
||||||
setList(nodeList.reverse())
|
|
||||||
setCollapseState(collapseState)
|
|
||||||
setLoading(false)
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
notify({
|
|
||||||
type: 'error',
|
|
||||||
message: `${err}`,
|
|
||||||
})
|
|
||||||
setLoading(false)
|
|
||||||
}
|
|
||||||
}, [notify])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (appDetail && runID)
|
|
||||||
getTracingList(appDetail.id, runID)
|
|
||||||
}, [appDetail, getTracingList, runID])
|
|
||||||
|
|
||||||
const collapseStateChange = (index: number) => {
|
|
||||||
const newCollapseState = produce(collapseState, (draft: boolean[]) => {
|
|
||||||
draft[index] = !draft[index]
|
|
||||||
})
|
|
||||||
setCollapseState(newCollapseState)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return (
|
|
||||||
<div className='flex h-full items-center justify-center bg-white'>
|
|
||||||
<Loading />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TracingPanel
|
|
||||||
list={list}
|
|
||||||
collapseState={collapseState}
|
|
||||||
collapseHandle={collapseStateChange}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Tracing
|
|
||||||
Loading…
Reference in New Issue
Block a user