pagination
This commit is contained in:
@@ -23,6 +23,7 @@ import {
|
||||
GridColDef,
|
||||
GridActionsCellItem,
|
||||
GridRenderCellParams,
|
||||
GridPaginationModel,
|
||||
} from '@mui/x-data-grid';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
@@ -34,6 +35,10 @@ import { ResourceConfig } from '../types/config';
|
||||
interface EnhancedTableProps {
|
||||
config: ResourceConfig;
|
||||
data: any[];
|
||||
total?: number;
|
||||
paginationModel?: GridPaginationModel;
|
||||
onPaginationModelChange?: (model: GridPaginationModel) => void;
|
||||
loading?: boolean;
|
||||
onEdit: (item: any) => void;
|
||||
onDelete: (id: string) => void;
|
||||
onCreate: () => void;
|
||||
@@ -43,6 +48,10 @@ interface EnhancedTableProps {
|
||||
export default function EnhancedTable({
|
||||
config,
|
||||
data,
|
||||
total,
|
||||
paginationModel,
|
||||
onPaginationModelChange,
|
||||
loading = false,
|
||||
onEdit,
|
||||
onDelete,
|
||||
onCreate,
|
||||
@@ -152,6 +161,23 @@ export default function EnhancedTable({
|
||||
rows={data || []}
|
||||
columns={columns}
|
||||
autoHeight
|
||||
paginationMode={config.pagination ? 'server' : 'client'}
|
||||
rowCount={(() => {
|
||||
if (!config.pagination) return data.length;
|
||||
if (total !== undefined) return total;
|
||||
|
||||
// Graceful fallback for missing total count
|
||||
const page = paginationModel?.page || 0;
|
||||
const pageSize = paginationModel?.pageSize || 10;
|
||||
if (data.length < pageSize) {
|
||||
return page * pageSize + data.length;
|
||||
}
|
||||
// Enable 'Next' button by pretending there's at least one more page
|
||||
return (page + 2) * pageSize;
|
||||
})()}
|
||||
loading={loading}
|
||||
paginationModel={paginationModel || { page: 0, pageSize: 10 }}
|
||||
onPaginationModelChange={onPaginationModelChange}
|
||||
getRowId={(row) => {
|
||||
const pk = config.primaryKey;
|
||||
if (row[pk] !== undefined && row[pk] !== null) return row[pk];
|
||||
@@ -162,11 +188,6 @@ export default function EnhancedTable({
|
||||
return `temp-id-${data.indexOf(row)}`;
|
||||
}}
|
||||
disableRowSelectionOnClick
|
||||
initialState={{
|
||||
pagination: {
|
||||
paginationModel: { page: 0, pageSize: 10 },
|
||||
},
|
||||
}}
|
||||
pageSizeOptions={[10, 25, 50]}
|
||||
sx={{
|
||||
border: 'none',
|
||||
|
||||
@@ -11,6 +11,8 @@ interface ResourceViewProps {
|
||||
onNavigateToResource?: (resourceName: string, id: string) => void;
|
||||
}
|
||||
|
||||
import { GridPaginationModel } from '@mui/x-data-grid';
|
||||
|
||||
export default function ResourceView({ config, onNavigateToResource }: ResourceViewProps) {
|
||||
const { id } = useParams();
|
||||
const location = useLocation();
|
||||
@@ -21,11 +23,26 @@ export default function ResourceView({ config, onNavigateToResource }: ResourceV
|
||||
const isView = !!id && !isEdit;
|
||||
const isList = !id && !isCreate;
|
||||
|
||||
const [paginationModel, setPaginationModel] = React.useState<GridPaginationModel>({
|
||||
page: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const { useList, useRead, useCreate, useUpdate, useDelete } = useResource(config);
|
||||
|
||||
const listQuery = useList();
|
||||
// Determine query parameters based on pagination config
|
||||
const queryParams = React.useMemo(() => {
|
||||
if (!config.pagination) return {};
|
||||
return {
|
||||
skip: paginationModel.page * paginationModel.pageSize,
|
||||
limit: paginationModel.pageSize,
|
||||
};
|
||||
}, [config.pagination, paginationModel]);
|
||||
|
||||
const listQuery = useList(queryParams);
|
||||
const itemQuery = useRead(id || "");
|
||||
|
||||
const paginatedData = listQuery.data || { data: [], total: undefined };
|
||||
const createMutation = useCreate();
|
||||
const updateMutation = useUpdate();
|
||||
const deleteMutation = useDelete();
|
||||
@@ -65,7 +82,11 @@ export default function ResourceView({ config, onNavigateToResource }: ResourceV
|
||||
{isList ? (
|
||||
<EnhancedTable
|
||||
config={config}
|
||||
data={listQuery.data || []}
|
||||
data={paginatedData.data || []}
|
||||
total={paginatedData.total}
|
||||
paginationModel={paginationModel}
|
||||
onPaginationModelChange={setPaginationModel}
|
||||
loading={listQuery.isFetching}
|
||||
onEdit={handleEdit}
|
||||
onDelete={handleDelete}
|
||||
onCreate={handleCreate}
|
||||
|
||||
@@ -38,6 +38,7 @@ export const configuration: Record<string, ResourceOverride> = {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
pagination: true,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,11 @@ export function useResource<T = any>(config: ResourceConfig) {
|
||||
queryFn: async () => {
|
||||
// @ts-ignore
|
||||
const res = await api.get<T[]>(endpoint, { params });
|
||||
return res.data;
|
||||
const total = res.headers ? parseInt(res.headers['x-total-count'] || res.headers['X-Total-Count']) : undefined;
|
||||
return {
|
||||
data: res.data,
|
||||
total: isNaN(total as any) ? undefined : total
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -77,7 +81,11 @@ export function useResource<T = any>(config: ResourceConfig) {
|
||||
queryFn: async () => {
|
||||
// @ts-ignore
|
||||
const res = await api.get<T[]>(endpoint, { params });
|
||||
return res.data;
|
||||
const total = res.headers ? parseInt(res.headers['x-total-count'] || res.headers['X-Total-Count']) : undefined;
|
||||
return {
|
||||
data: res.data,
|
||||
total: isNaN(total as any) ? undefined : total
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface ResourceConfig {
|
||||
endpoint: string;
|
||||
primaryKey: string;
|
||||
fields: Record<string, ResourceField>;
|
||||
pagination?: boolean;
|
||||
}
|
||||
|
||||
export interface AppConfig {
|
||||
|
||||
@@ -11,4 +11,5 @@ export interface FieldOverride {
|
||||
|
||||
export interface ResourceOverride {
|
||||
fields?: Record<string, FieldOverride>;
|
||||
pagination?: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user