mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-11 04:12:26 +00:00
fix client side pagination issue
This commit is contained in:
@@ -24,6 +24,8 @@ interface DataTablePaginationProps<TData> {
|
||||
isServerPagination?: boolean;
|
||||
isLoading?: boolean;
|
||||
disabled?: boolean;
|
||||
pageSize?: number;
|
||||
pageIndex?: number;
|
||||
}
|
||||
|
||||
export function DataTablePagination<TData>({
|
||||
@@ -33,10 +35,24 @@ export function DataTablePagination<TData>({
|
||||
totalCount,
|
||||
isServerPagination = false,
|
||||
isLoading = false,
|
||||
disabled = false
|
||||
disabled = false,
|
||||
pageSize: controlledPageSize,
|
||||
pageIndex: controlledPageIndex
|
||||
}: DataTablePaginationProps<TData>) {
|
||||
const t = useTranslations();
|
||||
|
||||
// Use controlled values if provided, otherwise fall back to table state
|
||||
const pageSize = controlledPageSize ?? table.getState().pagination.pageSize;
|
||||
const pageIndex = controlledPageIndex ?? table.getState().pagination.pageIndex;
|
||||
|
||||
// Calculate page boundaries based on controlled state
|
||||
// For server-side pagination, use totalCount if available for accurate page count
|
||||
const pageCount = isServerPagination && totalCount !== undefined
|
||||
? Math.ceil(totalCount / pageSize)
|
||||
: table.getPageCount();
|
||||
const canNextPage = pageIndex < pageCount - 1;
|
||||
const canPreviousPage = pageIndex > 0;
|
||||
|
||||
const handlePageSizeChange = (value: string) => {
|
||||
const newPageSize = Number(value);
|
||||
table.setPageSize(newPageSize);
|
||||
@@ -51,7 +67,7 @@ export function DataTablePagination<TData>({
|
||||
action: "first" | "previous" | "next" | "last"
|
||||
) => {
|
||||
if (isServerPagination && onPageChange) {
|
||||
const currentPage = table.getState().pagination.pageIndex;
|
||||
const currentPage = pageIndex;
|
||||
const pageCount = table.getPageCount();
|
||||
|
||||
let newPage: number;
|
||||
@@ -77,18 +93,24 @@ export function DataTablePagination<TData>({
|
||||
}
|
||||
} else {
|
||||
// Use table's built-in navigation for client-side pagination
|
||||
// But add bounds checking to prevent going beyond page boundaries
|
||||
const pageCount = table.getPageCount();
|
||||
switch (action) {
|
||||
case "first":
|
||||
table.setPageIndex(0);
|
||||
break;
|
||||
case "previous":
|
||||
table.previousPage();
|
||||
if (pageIndex > 0) {
|
||||
table.previousPage();
|
||||
}
|
||||
break;
|
||||
case "next":
|
||||
table.nextPage();
|
||||
if (pageIndex < pageCount - 1) {
|
||||
table.nextPage();
|
||||
}
|
||||
break;
|
||||
case "last":
|
||||
table.setPageIndex(table.getPageCount() - 1);
|
||||
table.setPageIndex(Math.max(0, pageCount - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -98,13 +120,13 @@ export function DataTablePagination<TData>({
|
||||
<div className="flex items-center justify-between text-muted-foreground">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Select
|
||||
value={`${table.getState().pagination.pageSize}`}
|
||||
value={`${pageSize}`}
|
||||
onValueChange={handlePageSizeChange}
|
||||
disabled={disabled}
|
||||
>
|
||||
<SelectTrigger className="h-8 w-[73px]" disabled={disabled}>
|
||||
<SelectValue
|
||||
placeholder={table.getState().pagination.pageSize}
|
||||
placeholder={pageSize}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent side="bottom">
|
||||
@@ -121,16 +143,11 @@ export function DataTablePagination<TData>({
|
||||
<div className="flex items-center justify-center text-sm font-medium">
|
||||
{isServerPagination && totalCount !== undefined
|
||||
? t("paginator", {
|
||||
current:
|
||||
table.getState().pagination.pageIndex + 1,
|
||||
last: Math.ceil(
|
||||
totalCount /
|
||||
table.getState().pagination.pageSize
|
||||
)
|
||||
current: pageIndex + 1,
|
||||
last: Math.ceil(totalCount / pageSize)
|
||||
})
|
||||
: t("paginator", {
|
||||
current:
|
||||
table.getState().pagination.pageIndex + 1,
|
||||
current: pageIndex + 1,
|
||||
last: table.getPageCount()
|
||||
})}
|
||||
</div>
|
||||
@@ -140,7 +157,7 @@ export function DataTablePagination<TData>({
|
||||
className="hidden h-8 w-8 p-0 lg:flex"
|
||||
onClick={() => handlePageNavigation("first")}
|
||||
disabled={
|
||||
!table.getCanPreviousPage() || isLoading || disabled
|
||||
!canPreviousPage || isLoading || disabled
|
||||
}
|
||||
>
|
||||
<span className="sr-only">{t("paginatorToFirst")}</span>
|
||||
@@ -151,7 +168,7 @@ export function DataTablePagination<TData>({
|
||||
className="h-8 w-8 p-0"
|
||||
onClick={() => handlePageNavigation("previous")}
|
||||
disabled={
|
||||
!table.getCanPreviousPage() || isLoading || disabled
|
||||
!canPreviousPage || isLoading || disabled
|
||||
}
|
||||
>
|
||||
<span className="sr-only">
|
||||
@@ -164,7 +181,7 @@ export function DataTablePagination<TData>({
|
||||
className="h-8 w-8 p-0"
|
||||
onClick={() => handlePageNavigation("next")}
|
||||
disabled={
|
||||
!table.getCanNextPage() || isLoading || disabled
|
||||
!canNextPage || isLoading || disabled
|
||||
}
|
||||
>
|
||||
<span className="sr-only">{t("paginatorToNext")}</span>
|
||||
@@ -175,7 +192,7 @@ export function DataTablePagination<TData>({
|
||||
className="hidden h-8 w-8 p-0 lg:flex"
|
||||
onClick={() => handlePageNavigation("last")}
|
||||
disabled={
|
||||
!table.getCanNextPage() || isLoading || disabled
|
||||
!canNextPage || isLoading || disabled
|
||||
}
|
||||
>
|
||||
<span className="sr-only">{t("paginatorToLast")}</span>
|
||||
|
||||
@@ -542,6 +542,8 @@ export function LogDataTable<TData, TValue>({
|
||||
isServerPagination={isServerPagination}
|
||||
isLoading={isLoading}
|
||||
disabled={disabled}
|
||||
pageSize={pageSize}
|
||||
pageIndex={currentPage}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
getSortedRowModel,
|
||||
ColumnFiltersState,
|
||||
getFilteredRowModel,
|
||||
VisibilityState
|
||||
VisibilityState,
|
||||
PaginationState
|
||||
} from "@tanstack/react-table";
|
||||
|
||||
// Extended ColumnDef type that includes optional friendlyName for column visibility dropdown
|
||||
@@ -227,6 +228,10 @@ export function DataTable<TData, TValue>({
|
||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>(
|
||||
initialColumnVisibility
|
||||
);
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: pageSize
|
||||
});
|
||||
const [activeTab, setActiveTab] = useState<string>(
|
||||
defaultTab || tabs?.[0]?.id || ""
|
||||
);
|
||||
@@ -256,6 +261,7 @@ export function DataTable<TData, TValue>({
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onGlobalFilterChange: setGlobalFilter,
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onPaginationChange: setPagination,
|
||||
initialState: {
|
||||
pagination: {
|
||||
pageSize: pageSize,
|
||||
@@ -267,21 +273,18 @@ export function DataTable<TData, TValue>({
|
||||
sorting,
|
||||
columnFilters,
|
||||
globalFilter,
|
||||
columnVisibility
|
||||
columnVisibility,
|
||||
pagination
|
||||
}
|
||||
});
|
||||
|
||||
// Persist pageSize to localStorage when it changes
|
||||
useEffect(() => {
|
||||
const currentPageSize = table.getState().pagination.pageSize;
|
||||
if (currentPageSize !== pageSize) {
|
||||
table.setPageSize(pageSize);
|
||||
|
||||
// Persist to localStorage if enabled
|
||||
if (persistPageSize) {
|
||||
setStoredPageSize(pageSize, tableId);
|
||||
}
|
||||
if (persistPageSize && pagination.pageSize !== pageSize) {
|
||||
setStoredPageSize(pagination.pageSize, tableId);
|
||||
setPageSize(pagination.pageSize);
|
||||
}
|
||||
}, [pageSize, table, persistPageSize, tableId]);
|
||||
}, [pagination.pageSize, persistPageSize, tableId, pageSize]);
|
||||
|
||||
useEffect(() => {
|
||||
// Persist column visibility to localStorage when it changes
|
||||
@@ -293,13 +296,13 @@ export function DataTable<TData, TValue>({
|
||||
const handleTabChange = (value: string) => {
|
||||
setActiveTab(value);
|
||||
// Reset to first page when changing tabs
|
||||
table.setPageIndex(0);
|
||||
setPagination(prev => ({ ...prev, pageIndex: 0 }));
|
||||
};
|
||||
|
||||
// Enhanced pagination component that updates our local state
|
||||
const handlePageSizeChange = (newPageSize: number) => {
|
||||
setPagination(prev => ({ ...prev, pageSize: newPageSize, pageIndex: 0 }));
|
||||
setPageSize(newPageSize);
|
||||
table.setPageSize(newPageSize);
|
||||
|
||||
// Persist immediately when changed
|
||||
if (persistPageSize) {
|
||||
@@ -614,6 +617,8 @@ export function DataTable<TData, TValue>({
|
||||
<DataTablePagination
|
||||
table={table}
|
||||
onPageSizeChange={handlePageSizeChange}
|
||||
pageSize={pagination.pageSize}
|
||||
pageIndex={pagination.pageIndex}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
Reference in New Issue
Block a user