Files
ragflow/web/src/pages/agents/agent-log-page.tsx
chanx 5f5c6a7990 Fix: Fixed the loss of Await Response function on the share page and other style issues #3221 (#9216)
### What problem does this PR solve?

Fix: Fixed the loss of Await Response function on the share page and
other style issues #3221

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-08-04 18:06:56 +08:00

367 lines
11 KiB
TypeScript

import TimeRangePicker from '@/components/originui/time-range-picker';
import { PageHeader } from '@/components/page-header';
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/components/ui/breadcrumb';
import { SearchInput } from '@/components/ui/input';
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
import { Spin } from '@/components/ui/spin';
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import { useFetchAgentLog } from '@/hooks/use-agent-request';
import {
IAgentLogMessage,
IAgentLogResponse,
} from '@/interfaces/database/agent';
import { IReferenceObject } from '@/interfaces/database/chat';
import { useQueryClient } from '@tanstack/react-query';
import React, { useEffect, useState } from 'react';
import { useParams } from 'umi';
import { DateRange } from '../../components/originui/calendar/index';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '../../components/ui/table';
import { useFetchDataOnMount } from '../agent/hooks/use-fetch-data';
import { AgentLogDetailModal } from './agent-log-detail-modal';
const getStartOfToday = (): Date => {
const today = new Date();
today.setHours(0, 0, 0, 0);
return today;
};
const getEndOfToday = (): Date => {
const today = new Date();
today.setHours(23, 59, 59, 999);
return today;
};
const AgentLogPage: React.FC = () => {
const { navigateToAgentList, navigateToAgent } = useNavigatePage();
const { flowDetail: agentDetail } = useFetchDataOnMount();
const { id: canvasId } = useParams();
const queryClient = useQueryClient();
const init = {
keywords: '',
from_date: getStartOfToday(),
to_date: getEndOfToday(),
orderby: 'create_time',
desc: false,
page: 1,
page_size: 10,
};
const [searchParams, setSearchParams] = useState(init);
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
},
{
title: 'Title',
dataIndex: 'title',
key: 'title',
render: (text, record: IAgentLogResponse) => (
<span>
{record?.message?.length ? record?.message[0]?.content : ''}
</span>
),
},
{
title: 'State',
dataIndex: 'state',
key: 'state',
render: (text, record: IAgentLogResponse) => (
<div
className="size-2 rounded-full"
style={{ backgroundColor: record.errors ? 'red' : 'green' }}
></div>
),
},
{
title: 'Number',
dataIndex: 'round',
key: 'round',
},
{
title: 'Latest Date',
dataIndex: 'update_date',
key: 'update_date',
sortable: true,
},
{
title: 'Create Date',
dataIndex: 'create_date',
key: 'create_date',
sortable: true,
},
];
const { data: logData, loading } = useFetchAgentLog(searchParams);
const { sessions: data, total } = logData || {};
const [currentDate, setCurrentDate] = useState<DateRange>({
from: searchParams.from_date,
to: searchParams.to_date,
});
const [keywords, setKeywords] = useState(searchParams.keywords);
const handleDateRangeChange = ({
from: startDate,
to: endDate,
}: DateRange) => {
setCurrentDate({ from: startDate, to: endDate });
};
const [pagination, setPagination] = useState<{
current: number;
pageSize: number;
total: number;
}>({
current: 1,
pageSize: 10,
total: total,
});
useEffect(() => {
setPagination((pre) => {
return {
...pre,
total: total,
};
});
}, [total]);
const [sortConfig, setSortConfig] = useState<{
orderby: string;
desc: boolean;
} | null>({ orderby: init.orderby, desc: init.desc ? true : false });
const handlePageChange = (current?: number, pageSize?: number) => {
console.log('current', current, 'pageSize', pageSize);
let page = current || 1;
if (pagination.pageSize !== pageSize) {
page = 1;
}
setPagination({
...pagination,
current: page,
pageSize: pageSize || 10,
});
};
const handleSearch = () => {
setSearchParams((pre) => {
return {
...pre,
from_date: currentDate.from as Date,
to_date: currentDate.to as Date,
page: pagination.current,
page_size: pagination.pageSize,
orderby: sortConfig?.orderby || '',
desc: sortConfig?.desc as boolean,
keywords: keywords,
};
});
};
const handleClickSearch = () => {
setPagination({ ...pagination, current: 1 });
handleSearch();
queryClient.invalidateQueries({
queryKey: ['fetchAgentLog'],
});
};
useEffect(() => {
handleSearch();
}, [pagination.current, pagination.pageSize, sortConfig]);
// handle sort
const handleSort = (key: string) => {
let desc = false;
if (sortConfig && sortConfig.orderby === key) {
desc = !sortConfig.desc;
}
setSortConfig({ orderby: key, desc });
};
const handleReset = () => {
setSearchParams(init);
setKeywords(init.keywords);
setCurrentDate({ from: init.from_date, to: init.to_date });
};
const [openModal, setOpenModal] = useState(false);
const [modalData, setModalData] = useState<IAgentLogResponse>();
const showLogDetail = (item: IAgentLogResponse) => {
if (item?.round) {
setModalData(item);
setOpenModal(true);
}
};
return (
<div className=" text-white">
<PageHeader>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink onClick={navigateToAgentList}>
Agent
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink onClick={navigateToAgent(canvasId as string)}>
{agentDetail.title}
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Log</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</PageHeader>
<div className="p-4">
<div className="flex justify-between items-center">
<h1 className="text-2xl font-bold mb-4">Log</h1>
<div className="flex justify-end space-x-2 mb-4 text-foreground">
<div className="flex items-center space-x-2">
<span>ID/Title</span>
<SearchInput
value={keywords}
onChange={(e) => {
setKeywords(e.target.value);
}}
className="w-32"
></SearchInput>
</div>
<div className="flex items-center space-x-2">
<span className="whitespace-nowrap">Latest Date</span>
<TimeRangePicker
onSelect={handleDateRangeChange}
selectDateRange={currentDate}
/>
</div>
<button
type="button"
className="bg-foreground text-text-title-invert px-4 py-1 rounded"
onClick={() => {
handleClickSearch();
}}
>
Search
</button>
<button
type="button"
className="bg-transparent text-foreground px-4 py-1 rounded border"
onClick={() => handleReset()}
>
Reset
</button>
</div>
</div>
<div className="border rounded-md overflow-auto">
{/* <div className="max-h-[500px] overflow-y-auto w-full"> */}
<Table rootClassName="max-h-[calc(100vh-200px)]">
<TableHeader className="sticky top-0 bg-background z-10 shadow-sm">
<TableRow>
{columns.map((column) => (
<TableHead
key={column.dataIndex}
onClick={
column.sortable
? () => handleSort(column.dataIndex)
: undefined
}
className={
column.sortable ? 'cursor-pointer hover:bg-muted/50' : ''
}
>
<div className="flex items-center">
{column.title}
{column.sortable &&
sortConfig?.orderby === column.dataIndex && (
<span className="ml-1">
{sortConfig.desc ? '↓' : '↑'}
</span>
)}
</div>
</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{loading && (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
<Spin size="large">
<span className="sr-only">Loading...</span>
</Spin>
</TableCell>
</TableRow>
)}
{!loading &&
data?.map((item) => (
<TableRow
key={item.id}
onClick={() => {
showLogDetail(item);
}}
>
{columns.map((column) => (
<TableCell key={column.dataIndex}>
{column.render
? column.render(item[column.dataIndex], item)
: item[column.dataIndex]}
</TableCell>
))}
</TableRow>
))}
{!loading && (!data || data.length === 0) && (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No data
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
{/* </div> */}
</div>
<div className="flex justify-end mt-4 w-full">
<div className="space-x-2">
<RAGFlowPagination
{...pagination}
total={pagination.total}
onChange={(page, pageSize) => {
handlePageChange(page, pageSize);
}}
></RAGFlowPagination>
</div>
</div>
</div>
<AgentLogDetailModal
isOpen={openModal}
message={modalData?.message as IAgentLogMessage[]}
reference={modalData?.reference as unknown as IReferenceObject}
onClose={() => setOpenModal(false)}
/>
</div>
);
};
export default AgentLogPage;