import * as React from "react"; import { useQuery } from "react-query"; import { useTable, useSortBy, usePagination, useFilters, Column } from "react-table"; import { ChevronDoubleLeftIcon, ChevronLeftIcon, ChevronRightIcon, ChevronDoubleRightIcon } from "@heroicons/react/solid"; import { APIClient } from "../../api/APIClient"; import { EmptyListState } from "../../components/emptystates"; import * as Icons from "../../components/Icons"; import * as DataTable from "../../components/data-table"; import { IndexerSelectColumnFilter, PushStatusSelectColumnFilter, SearchColumnFilter } from "./Filters"; type TableState = { queryPageIndex: number; queryPageSize: number; totalCount: number; queryFilters: ReleaseFilter[]; }; const initialState: TableState = { queryPageIndex: 0, queryPageSize: 10, totalCount: 0, queryFilters: [] }; enum ActionType { PAGE_CHANGED = "PAGE_CHANGED", PAGE_SIZE_CHANGED = "PAGE_SIZE_CHANGED", TOTAL_COUNT_CHANGED = "TOTAL_COUNT_CHANGED", FILTER_CHANGED = "FILTER_CHANGED" } type Actions = | { type: ActionType.FILTER_CHANGED; payload: ReleaseFilter[]; } | { type: ActionType.PAGE_CHANGED; payload: number; } | { type: ActionType.PAGE_SIZE_CHANGED; payload: number; } | { type: ActionType.TOTAL_COUNT_CHANGED; payload: number; }; const TableReducer = (state: TableState, action: Actions): TableState => { switch (action.type) { case ActionType.PAGE_CHANGED: return { ...state, queryPageIndex: action.payload }; case ActionType.PAGE_SIZE_CHANGED: return { ...state, queryPageSize: action.payload }; case ActionType.FILTER_CHANGED: return { ...state, queryFilters: action.payload }; case ActionType.TOTAL_COUNT_CHANGED: return { ...state, totalCount: action.payload }; default: throw new Error(`Unhandled action type: ${action}`); } }; export const ReleaseTable = () => { const columns = React.useMemo(() => [ { Header: "Age", accessor: "timestamp", Cell: DataTable.AgeCell }, { Header: "Release", accessor: "torrent_name", Cell: DataTable.TitleCell, Filter: SearchColumnFilter }, { Header: "Actions", accessor: "action_status", Cell: DataTable.ReleaseStatusCell, Filter: PushStatusSelectColumnFilter }, { Header: "Indexer", accessor: "indexer", Cell: DataTable.TitleCell, Filter: IndexerSelectColumnFilter, filter: "equal" } ] as Column[], []); const [{ queryPageIndex, queryPageSize, totalCount, queryFilters }, dispatch] = React.useReducer(TableReducer, initialState); const { isLoading, error, data, isSuccess } = useQuery( ["releases", queryPageIndex, queryPageSize, queryFilters], () => APIClient.release.findQuery(queryPageIndex * queryPageSize, queryPageSize, queryFilters), { keepPreviousData: true, staleTime: 5000 } ); // Use the state and functions returned from useTable to build your UI const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page, // Instead of using 'rows', we'll use page, // which has only the rows for the active page // The rest of these things are super handy, too ;) canPreviousPage, canNextPage, pageOptions, pageCount, gotoPage, nextPage, previousPage, setPageSize, state: { pageIndex, pageSize, filters } } = useTable( { columns, data: data && isSuccess ? data.data : [], initialState: { pageIndex: queryPageIndex, pageSize: queryPageSize, filters: [] }, manualPagination: true, manualFilters: true, manualSortBy: true, pageCount: isSuccess ? Math.ceil(totalCount / queryPageSize) : 0, autoResetSortBy: false, autoResetExpanded: false, autoResetPage: false }, useFilters, useSortBy, usePagination ); React.useEffect(() => { dispatch({ type: ActionType.PAGE_CHANGED, payload: pageIndex }); }, [pageIndex]); React.useEffect(() => { dispatch({ type: ActionType.PAGE_SIZE_CHANGED, payload: pageSize }); gotoPage(0); }, [pageSize, gotoPage]); React.useEffect(() => { if (data?.count) { dispatch({ type: ActionType.TOTAL_COUNT_CHANGED, payload: data.count }); } }, [data?.count]); React.useEffect(() => { dispatch({ type: ActionType.FILTER_CHANGED, payload: filters }); }, [filters]); if (error) return

Error

; if (isLoading) return

Loading...

; if (!data) return ; // Render the UI for your table return (
{headerGroups.map((headerGroup) => headerGroup.headers.map((column) => ( column.Filter ? ( {column.render("Filter")} ) : null )) )}
{headerGroups.map((headerGroup) => { const { key: rowKey, ...rowRest } = headerGroup.getHeaderGroupProps(); return ( {headerGroup.headers.map((column) => { const { key: columnKey, ...columnRest } = column.getHeaderProps(column.getSortByToggleProps()); return ( // Add the sorting props to control sorting. For this example // we can add them into the header props ); })} ); })} {page.map((row) => { prepareRow(row); const { key: bodyRowKey, ...bodyRowRest } = row.getRowProps(); return ( {row.cells.map((cell) => { const { key: cellRowKey, ...cellRowRest } = cell.getCellProps(); return ( ); })} ); })}
<>{column.render("Header")} {/* Add a sort direction indicator */} {column.isSorted ? ( column.isSortedDesc ? ( ) : ( ) ) : ( )}
<>{cell.render("Cell")}
{/* Pagination */}
previousPage()} disabled={!canPreviousPage}>Previous nextPage()} disabled={!canNextPage}>Next
Page {pageIndex + 1} of {pageOptions.length}
); };