Spaces:
Running
Running
import { ChangeEventHandler, FC, useCallback, useEffect, useMemo, useState } from "react"; | |
import { useSearchParams } from "react-router-dom"; | |
import Select from "react-select"; | |
import { | |
useActivateDataset, | |
useCreateDatasetsDraft, | |
useDeleteDataset, | |
useDeleteFileFromDataset, | |
useGetDatasets, | |
} from "@/api/documents/hooks"; | |
import Button from "@/components/generics/button/Button"; | |
import Modal from "@/components/generics/modal/Modal"; | |
import { DocsList } from "@/components/views/documents/docsList/DocsList"; | |
import { CreateDatasetForm } from "@/components/views/documents/createDatasetForm/CreateDatasetForm"; | |
import { AddDocumentForm } from "@/components/views/documents/addDocuimentForm/AddDocumentForm"; | |
import "./Logs.scss"; | |
import { downloadDocument } from "@/api/documents/documentsApi"; | |
import Input from "@/components/generics/input/Input"; | |
import Spinner from "@/components/generics/spinner/Spinner"; | |
import Tag from "@/components/generics/tag/Tag"; | |
import Tooltip from "@/components/generics/tooltip/Tooltip"; | |
import { Pagination } from "@/components/views/pagination/Pagination"; | |
import { SortDirectionsTooltipMap, StatusMap } from "@/shared/constants"; | |
import { GoSearch, GoDownload, GoTrash, GoTriangleUp, GoTriangleDown } from "react-icons/go"; | |
import { useGetLogs } from "@/api/logs/hooks"; | |
import { GetLogsRequestParams, LogItemType, SortDirections } from "@/api/logs/types"; | |
import Documents from "../documentsPage/Documents"; | |
import LogDetailsModal from "./LogDetailsModal"; | |
import DatePicker from "react-datepicker"; | |
import "react-datepicker/dist/react-datepicker.css"; | |
import axios from 'axios'; | |
import { downloadLogsAsExcel } from "@/api/logs/logsApi"; | |
const Logs: FC = () => { | |
const [page, setPage] = useState<number>(0); | |
const [pageSize, setPageSize] = useState<number>(50); | |
const [userInput, setUserInput] = useState<string | undefined>(undefined); | |
const [user, setUser] = useState<string | undefined>(undefined); | |
const [chatIdFilter, setChatIdFilter] = useState<string | undefined>(undefined); | |
const [sort, setSort] = useState<undefined | { field: string; direction: SortDirections }[]>(undefined); | |
const [dateTo, setDateTo] = useState<Date | undefined>(undefined); | |
const [dateFrom, setDateFrom] = useState<Date | undefined>(undefined); | |
const { data: logsData, isLoading } = useGetLogs({ | |
page, page_size: pageSize, | |
user_name: user, sort, | |
date_to: dateTo, date_from: dateFrom, | |
chat_id: chatIdFilter | |
}); | |
const [isModalOpen, setIsModalOpen] = useState(false); | |
const [selectedLog, setSelectedLog] = useState<LogItemType | null>(null); | |
const [searchParams, setSearchParams] = useSearchParams(); | |
// const handleFilterList = () => { | |
// const localStartDate = dateFrom ? new Date(dateFrom) : undefined; | |
// localStartDate?.setHours(0, 0, 0, 0); | |
// const localEndDate = dateTo ? new Date(dateTo) : undefined; | |
// localEndDate?.setHours(23, 59, 59, 999); | |
// setDateFrom(localStartDate ? new Date(localStartDate) : undefined); | |
// setDateTo(localEndDate ? new Date(localEndDate) : undefined); | |
// setPage(0); | |
// }; | |
const openDetailsModal = (log: LogItemType) => { | |
setSelectedLog(log) | |
setIsModalOpen(true); | |
}; | |
const closeModal = () => { | |
setSelectedLog(null); | |
setIsModalOpen(false); | |
}; | |
const toggleSort = (field: string) => { | |
setSort((prevSort) => { | |
if (prevSort?.length && prevSort?.length > 0) { | |
const newSort = [...prevSort]; | |
const existingFieldIndex = prevSort?.findIndex((e) => e.field === field); | |
const currentDirection = prevSort[existingFieldIndex]?.direction; | |
if (existingFieldIndex != null && existingFieldIndex !== -1) { | |
const newSort = [...prevSort]; | |
if (currentDirection === SortDirections.asc) { | |
newSort[existingFieldIndex] = { field, direction: SortDirections.desc }; | |
return newSort; | |
} else if (currentDirection === SortDirections.desc) { | |
newSort.splice(existingFieldIndex, 1); | |
return newSort; | |
} | |
} else { | |
newSort.push({ field, direction: SortDirections.asc }); | |
} | |
return newSort; | |
} else { | |
return [{ field, direction: SortDirections.asc }]; | |
} | |
}); | |
}; | |
const sorting = (field: string) => { | |
const currentDirection = sort?.find((e) => e.field === field)?.direction; | |
return ( | |
<Tooltip text={SortDirectionsTooltipMap[currentDirection ?? "empty"]}> | |
<Button | |
onClick={() => toggleSort(field)} | |
icon={ | |
<div className="sort-btn"> | |
<GoTriangleUp viewBox="0 0 20 20" className={currentDirection === SortDirections.asc ? "active" : ""} /> | |
<GoTriangleDown | |
viewBox="0 0 20 20" | |
className={currentDirection === SortDirections.desc ? "arrow-down active" : "arrow-down"} | |
/> | |
</div> | |
} | |
buttonType="link" | |
/> | |
</Tooltip> | |
); | |
}; | |
// useEffect(() => { | |
// if ( | |
// (!searchParams.get("datasetId") || | |
// !datasetsData?.find((e) => e.id.toString() == searchParams.get("datasetId"))) && | |
// datasetsData?.[0]?.id | |
// ) { | |
// setSearchParams({ datasetId: String(datasetsData?.[0]?.id) }); | |
// } | |
// }, [datasetsData, searchParams, setSearchParams]); | |
const handleDownloadExcel = useCallback(async () => { | |
const params: GetLogsRequestParams = { | |
user_name: user, | |
date_from: dateFrom, | |
date_to: dateTo, | |
sort, | |
chat_id: chatIdFilter | |
}; | |
downloadLogsAsExcel(params, "Логи запросов"); | |
}, [user, dateFrom, dateTo, sort, chatIdFilter]); | |
const handleChatIdChange = (event: any) => { | |
setChatIdFilter(event.target.value); | |
}; | |
return ( | |
<div className="documents-page"> | |
<div className="filters-container"> | |
<div className="date-picker-container"> | |
<label htmlFor="startDate">Показать логи с</label> | |
<DatePicker | |
id="startDate" | |
dateFormat="dd/MM/yyyy" | |
selected={dateFrom} | |
onChange={(date) => setDateFrom(date ?? undefined)} | |
selectsStart | |
isClearable={true} | |
showIcon | |
/> | |
</div> | |
<div className="date-picker-container"> | |
<label htmlFor="endDate">по</label> | |
<DatePicker | |
id="endDate" | |
dateFormat="dd/MM/yyyy" | |
selected={dateTo} | |
onChange={(date) => setDateTo(date ?? undefined)} | |
selectsEnd | |
isClearable={true} | |
showIcon | |
/> | |
</div> | |
<label htmlFor="endDate">Чат ID: | |
<input type="text" value={chatIdFilter} onChange={handleChatIdChange} /> | |
</label> | |
</div> | |
<div className="filters-container"> | |
<Button name="Скачать в Excel" onClick={handleDownloadExcel} icon={<GoDownload />} /> | |
</div> | |
<div className="docs-table-container" style={{ position: "relative" }}> | |
{isLoading && ( | |
<div className="loading-overlay"> | |
<Spinner /> | |
</div> | |
)} | |
<table className="docs-table"> | |
<thead> | |
<tr> | |
<th style={{ width: "50%" }}> | |
<div className="name-with-sort"> | |
<span>Время</span> | |
{sorting("date_created")} | |
</div> | |
</th> | |
<th> | |
<div className="name-with-sort"> | |
<span>Пользователь</span> | |
</div> | |
</th> | |
<th> | |
<div className="name-with-sort"> | |
<span>Чат</span> | |
</div> | |
</th> | |
<th> | |
<div className="name-with-sort"> | |
<span>Запрос</span> | |
</div> | |
</th> | |
<th> | |
<div className="name-with-sort"> | |
<span>Ответ</span> | |
</div> | |
</th> | |
<th></th> | |
</tr> | |
</thead> | |
<tbody> | |
{logsData?.data.map((log) => ( | |
<tr key={log.id} onClick={() => openDetailsModal(log)}> | |
<td>{log.date_created ? new Date(log.date_created).toLocaleDateString() : ''} {log.date_created ? new Date(log.date_created).toLocaleTimeString() : ''}</td> | |
<td>{log.user_name}</td> | |
<td className="ellipsis" style={{ maxWidth: "100px" }}>{log.chat_id}</td> | |
<td className="ellipsis">{log.user_request}</td> | |
<td className="ellipsis">{log.llm_result}</td> | |
</tr> | |
))} | |
</tbody> | |
</table> | |
</div> | |
<Pagination | |
total={logsData?.data.total ?? 0} | |
pageNumber={logsData?.data.page ? logsData?.data.page : page} | |
pageSize={logsData?.data.page_size ?? 50} | |
setPageSize={setPageSize} | |
setPage={setPage} | |
/> | |
{selectedLog !== null ? (<LogDetailsModal | |
isOpen={isModalOpen} | |
onRequestClose={closeModal} | |
log={selectedLog} | |
setChatIdFilter={setChatIdFilter} | |
/>) : ''} | |
</div> | |
); | |
}; | |
export default Logs; | |