From 1fce1a61d46ed6029e3d1732f7ee0130ec5a3b42 Mon Sep 17 00:00:00 2001 From: lyzno1 <92089059+lyzno1@users.noreply.github.com> Date: Tue, 2 Sep 2025 16:43:11 +0800 Subject: [PATCH] feat(workflow-log): enhance workflow logs UI with sorting and status filters (#24978) --- .../console/app/workflow_app_log.py | 4 +- .../components/app/workflow-log/filter.tsx | 25 ++++++------ web/app/components/app/workflow-log/list.tsx | 39 +++++++++++++++++-- web/i18n/en-US/app-log.ts | 2 +- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/api/controllers/console/app/workflow_app_log.py b/api/controllers/console/app/workflow_app_log.py index 8d8cdc93cf..76f02041ef 100644 --- a/api/controllers/console/app/workflow_app_log.py +++ b/api/controllers/console/app/workflow_app_log.py @@ -27,7 +27,9 @@ class WorkflowAppLogApi(Resource): """ parser = reqparse.RequestParser() parser.add_argument("keyword", type=str, location="args") - parser.add_argument("status", type=str, choices=["succeeded", "failed", "stopped"], location="args") + parser.add_argument( + "status", type=str, choices=["succeeded", "failed", "stopped", "partial-succeeded"], location="args" + ) parser.add_argument( "created_at__before", type=str, location="args", help="Filter logs created before this timestamp" ) diff --git a/web/app/components/app/workflow-log/filter.tsx b/web/app/components/app/workflow-log/filter.tsx index f60e1f9da2..6b8232a454 100644 --- a/web/app/components/app/workflow-log/filter.tsx +++ b/web/app/components/app/workflow-log/filter.tsx @@ -33,18 +33,6 @@ const Filter: FC = ({ queryParams, setQueryParams }: IFilterProps) const { t } = useTranslation() return (
- { - setQueryParams({ ...queryParams, status: item.value as string }) - }} - onClear={() => setQueryParams({ ...queryParams, status: 'all' })} - items={[{ value: 'all', name: 'All' }, - { value: 'succeeded', name: 'Success' }, - { value: 'failed', name: 'Fail' }, - { value: 'stopped', name: 'Stop' }, - ]} - /> = ({ queryParams, setQueryParams }: IFilterProps) onClear={() => setQueryParams({ ...queryParams, period: '9' })} items={Object.entries(TIME_PERIOD_MAPPING).map(([k, v]) => ({ value: k, name: t(`appLog.filter.period.${v.name}`) }))} /> + { + setQueryParams({ ...queryParams, status: item.value as string }) + }} + onClear={() => setQueryParams({ ...queryParams, status: 'all' })} + items={[{ value: 'all', name: 'All' }, + { value: 'succeeded', name: 'Success' }, + { value: 'partial-succeeded', name: 'Partial Success' }, + { value: 'failed', name: 'Failure' }, + { value: 'stopped', name: 'Stop' }, + ]} + /> = ({ logs, appDetail, onRefresh }) => { const [showDrawer, setShowDrawer] = useState(false) const [currentLog, setCurrentLog] = useState() + const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc') + const [localLogs, setLocalLogs] = useState(logs?.data || []) + + useEffect(() => { + if (!logs?.data) { + setLocalLogs([]) + return + } + + const sortedLogs = [...logs.data].sort((a, b) => { + const result = a.created_at - b.created_at + return sortOrder === 'asc' ? result : -result + }) + + setLocalLogs(sortedLogs) + }, [logs?.data, sortOrder]) + + const handleSort = () => { + setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc') + } const isWorkflow = appDetail?.mode === 'workflow' @@ -45,7 +66,7 @@ const WorkflowAppLogList: FC = ({ logs, appDetail, onRefresh }) => { return (
- Fail + Failure
) } @@ -90,7 +111,17 @@ const WorkflowAppLogList: FC = ({ logs, appDetail, onRefresh }) => { - {t('appLog.table.header.startTime')} + +
+ {t('appLog.table.header.startTime')} + +
+ {t('appLog.table.header.status')} {t('appLog.table.header.runtime')} {t('appLog.table.header.tokens')} @@ -99,7 +130,7 @@ const WorkflowAppLogList: FC = ({ logs, appDetail, onRefresh }) => { - {logs.data.map((log: WorkflowAppLogDetail) => { + {localLogs.map((log: WorkflowAppLogDetail) => { const endUser = log.created_by_end_user ? log.created_by_end_user.session_id : log.created_by_account ? log.created_by_account.name : defaultValue return