Spaces:
Running
Running
| import "./DocsList.scss"; | |
| import { FC, useState } from "react"; | |
| import { GoDownload, GoSearch, GoTrash, GoTriangleDown, GoTriangleUp } from "react-icons/go"; | |
| import { SortDirectionsTooltipMap, StatusMap } from "@/shared/constants"; | |
| import Button from "@/components/generics/button/Button"; | |
| import { DocsListProps } from "./DocsList.interface"; | |
| import Input from "@/components/generics/input/Input"; | |
| import { Pagination } from "../../pagination/Pagination"; | |
| import { SortDirections } from "@/api/documents/types"; | |
| import Spinner from "@/components/generics/spinner/Spinner"; | |
| import Tag from "@/components/generics/tag/Tag"; | |
| import Tooltip from "@/components/generics/tooltip/Tooltip"; | |
| import { downloadDocument } from "@/api/documents/documentsApi"; | |
| import { useGetDataset } from "@/api/documents/hooks"; | |
| export const DocsList: FC<DocsListProps> = ({ datasetId, handleDeleteFile }) => { | |
| const [page, setPage] = useState<number>(0); | |
| const [pageSize, setPageSize] = useState<number>(10); | |
| const [searchInput, setSearchInput] = useState<string | undefined>(undefined); | |
| const [search, setSearch] = useState<string | undefined>(undefined); | |
| const [sort, setSort] = useState<undefined | { field: string; direction: SortDirections }[]>(undefined); | |
| const { data: datasetData, isFetching } = useGetDataset(datasetId ?? -1, { page, page_size: pageSize, search, sort }); | |
| 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 handleEnterPress = (event: React.KeyboardEvent<HTMLInputElement>) => { | |
| if (event.key === "Enter" && searchInput) { | |
| setSearch(searchInput); | |
| setPage(0); | |
| } | |
| }; | |
| 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> | |
| ); | |
| }; | |
| return ( | |
| <> | |
| <div className="docs-search-input"> | |
| <Input | |
| name="" | |
| placeholder="Введите название документа" | |
| value={searchInput} | |
| onSetValue={setSearchInput} | |
| onKeyDown={handleEnterPress} | |
| extra={ | |
| <Tooltip text="Поиск"> | |
| <Button | |
| buttonType="link" | |
| icon={<GoSearch style={{ width: "19px", height: "19px" }} />} | |
| onClick={() => { | |
| setSearch(searchInput); | |
| setPage(0); | |
| }} | |
| /> | |
| </Tooltip> | |
| } | |
| /> | |
| </div> | |
| <div className="docs-table-container" style={{ position: "relative" }}> | |
| {isFetching && ( | |
| <div className="loading-overlay"> | |
| <Spinner /> | |
| </div> | |
| )} | |
| <table className="docs-table"> | |
| <thead> | |
| <tr> | |
| <th style={{ width: "50%" }}> | |
| <div className="name-with-sort"> | |
| <span>Название документа</span> | |
| {sorting("name")} | |
| </div> | |
| </th> | |
| <th> | |
| <div className="name-with-sort"> | |
| <span>Владелец</span> | |
| {sorting("owner")} | |
| </div> | |
| </th> | |
| <th> | |
| <div className="name-with-sort"> | |
| <span>Статус</span> | |
| {sorting("status")} | |
| </div> | |
| </th> | |
| <th></th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {datasetData?.data.page.map((doc) => ( | |
| <tr key={doc.id}> | |
| <td>{doc.name}</td> | |
| <td>{doc.owner}</td> | |
| <td> | |
| <Tag text={doc.status} type={StatusMap[doc.status]} /> | |
| </td> | |
| <td> | |
| <div className="actions"> | |
| <Button | |
| onClick={() => downloadDocument(datasetData.id, doc.id.toString(), doc.name)} | |
| icon={<GoDownload />} | |
| buttonType="link" | |
| /> | |
| <Button onClick={() => handleDeleteFile(doc.id)} icon={<GoTrash />} buttonType="link" /> | |
| </div> | |
| </td> | |
| </tr> | |
| ))} | |
| </tbody> | |
| </table> | |
| </div> | |
| <Pagination | |
| total={datasetData?.data.total ?? 0} | |
| pageNumber={datasetData?.data.pageNumber ? datasetData?.data.pageNumber : page} | |
| pageSize={datasetData?.data.pageSize ?? 20} | |
| setPageSize={setPageSize} | |
| setPage={setPage} | |
| /> | |
| </> | |
| ); | |
| }; | |