mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-01 19:20:55 +00:00
[UI] Stored table state (#9902)
* Add useStoredTableState zustand * Store table page size in the zustand state * Store tablesorting data in zustand state * Actually provide records... * Transfer table names state * Store hidden columns too
This commit is contained in:
@ -52,19 +52,16 @@ export type TableState = {
|
||||
hasSelectedRecords: boolean;
|
||||
setSelectedRecords: (records: any[]) => void;
|
||||
clearSelectedRecords: () => void;
|
||||
hiddenColumns: string[] | null;
|
||||
setHiddenColumns: (columns: string[]) => void;
|
||||
searchTerm: string;
|
||||
setSearchTerm: (term: string) => void;
|
||||
recordCount: number;
|
||||
setRecordCount: (count: number) => void;
|
||||
page: number;
|
||||
setPage: (page: number) => void;
|
||||
pageSize: number;
|
||||
setPageSize: (pageSize: number) => void;
|
||||
storedDataLoaded: boolean;
|
||||
records: any[];
|
||||
setRecords: (records: any[]) => void;
|
||||
updateRecord: (record: any) => void;
|
||||
hiddenColumns: string[];
|
||||
setHiddenColumns: (columns: string[]) => void;
|
||||
idAccessor?: string;
|
||||
};
|
||||
|
@ -8,6 +8,7 @@ import { useShallow } from 'zustand/react/shallow';
|
||||
import { api } from '../App';
|
||||
import { useLocalState } from '../states/LocalState';
|
||||
import { useServerApiState } from '../states/ServerApiState';
|
||||
import { useStoredTableState } from '../states/StoredTableState';
|
||||
import { fetchGlobalStates } from '../states/states';
|
||||
|
||||
export const defaultLocale = 'en';
|
||||
@ -117,7 +118,7 @@ export function LanguageContext({
|
||||
fetchGlobalStates();
|
||||
|
||||
// Clear out cached table column names
|
||||
useLocalState.getState().clearTableColumnNames();
|
||||
useStoredTableState.getState().clearTableColumnNames();
|
||||
})
|
||||
/* istanbul ignore next */
|
||||
.catch((err) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { randomId, useLocalStorage } from '@mantine/hooks';
|
||||
import { randomId } from '@mantine/hooks';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
@ -6,12 +6,6 @@ import type { FilterSetState } from '@lib/types/Filters';
|
||||
import type { TableState } from '@lib/types/Tables';
|
||||
import { useFilterSet } from './UseFilterSet';
|
||||
|
||||
// Interface for the stored table data in local storage
|
||||
interface StoredTableData {
|
||||
pageSize: number;
|
||||
hiddenColumns: string[] | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom hook for managing the state of an <InvenTreeTable> component.
|
||||
*
|
||||
@ -51,6 +45,9 @@ export function useTable(tableName: string, idAccessor = 'pk'): TableState {
|
||||
[expandedRecords]
|
||||
);
|
||||
|
||||
// Array of columns which are hidden
|
||||
const [hiddenColumns, setHiddenColumns] = useState<string[]>([]);
|
||||
|
||||
// Array of selected records
|
||||
const [selectedRecords, setSelectedRecords] = useState<any[]>([]);
|
||||
|
||||
@ -73,70 +70,6 @@ export function useTable(tableName: string, idAccessor = 'pk'): TableState {
|
||||
|
||||
const [page, setPage] = useState<number>(1);
|
||||
|
||||
const [storedDataLoaded, setStoredDataLoaded] = useState<boolean>(false);
|
||||
|
||||
const [tableData, setTableData] = useState<StoredTableData>({
|
||||
pageSize: 25,
|
||||
hiddenColumns: null
|
||||
});
|
||||
|
||||
const [storedTableData, setStoredTableData] =
|
||||
useLocalStorage<StoredTableData>({
|
||||
key: `inventree-table-data-${tableName}`,
|
||||
getInitialValueInEffect: true,
|
||||
// sync: false, // Do not use this option - see below
|
||||
defaultValue: {
|
||||
pageSize: 25,
|
||||
hiddenColumns: null
|
||||
},
|
||||
deserialize: (value: any) => {
|
||||
const tableData =
|
||||
value === undefined
|
||||
? {
|
||||
pageSize: 25,
|
||||
hiddenColumns: null
|
||||
}
|
||||
: JSON.parse(value);
|
||||
|
||||
if (!storedDataLoaded) {
|
||||
setStoredDataLoaded((wasLoaded: boolean) => {
|
||||
if (!wasLoaded) {
|
||||
// First load of stored table data - copy to local state
|
||||
// We only do this on first load, to avoid live syncing between tabs
|
||||
// Note: The 'sync: false' option is not used, it does not perform as expected
|
||||
setTableData(tableData);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return tableData;
|
||||
}
|
||||
});
|
||||
|
||||
const setPageSize = useCallback((size: number) => {
|
||||
setStoredTableData((prev) => ({
|
||||
...prev,
|
||||
pageSize: size
|
||||
}));
|
||||
setTableData((prev) => ({
|
||||
...prev,
|
||||
pageSize: size
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const setHiddenColumns = useCallback((columns: string[] | null) => {
|
||||
setStoredTableData((prev) => {
|
||||
return {
|
||||
...prev,
|
||||
hiddenColumns: columns
|
||||
};
|
||||
});
|
||||
setTableData((prev) => ({
|
||||
...prev,
|
||||
hiddenColumns: columns
|
||||
}));
|
||||
}, []);
|
||||
|
||||
// Search term
|
||||
const [searchTerm, setSearchTerm] = useState<string>('');
|
||||
|
||||
@ -186,17 +119,14 @@ export function useTable(tableName: string, idAccessor = 'pk'): TableState {
|
||||
setSelectedRecords,
|
||||
clearSelectedRecords,
|
||||
hasSelectedRecords,
|
||||
pageSize: tableData.pageSize,
|
||||
hiddenColumns: tableData.hiddenColumns,
|
||||
setHiddenColumns,
|
||||
searchTerm,
|
||||
setSearchTerm,
|
||||
recordCount,
|
||||
setRecordCount,
|
||||
hiddenColumns,
|
||||
setHiddenColumns,
|
||||
page,
|
||||
setPage,
|
||||
setPageSize,
|
||||
storedDataLoaded,
|
||||
records,
|
||||
setRecords,
|
||||
updateRecord,
|
||||
|
@ -1,4 +1,3 @@
|
||||
import type { DataTableSortStatus } from 'mantine-datatable';
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
@ -35,17 +34,6 @@ interface LocalStateProps {
|
||||
// panels
|
||||
lastUsedPanels: Record<string, string>;
|
||||
setLastUsedPanel: (panelKey: string) => (value: string) => void;
|
||||
tableColumnNames: Record<string, Record<string, string>>;
|
||||
getTableColumnNames: (tableKey: string) => Record<string, string>;
|
||||
setTableColumnNames: (
|
||||
tableKey: string
|
||||
) => (names: Record<string, string>) => void;
|
||||
tableSorting: Record<string, any>;
|
||||
getTableSorting: (tableKey: string) => DataTableSortStatus;
|
||||
setTableSorting: (
|
||||
tableKey: string
|
||||
) => (sorting: DataTableSortStatus<any>) => void;
|
||||
clearTableColumnNames: () => void;
|
||||
detailDrawerStack: number;
|
||||
addDetailDrawer: (value: number | false) => void;
|
||||
navigationOpen: boolean;
|
||||
@ -140,36 +128,7 @@ export const useLocalState = create<LocalStateProps>()(
|
||||
});
|
||||
}
|
||||
},
|
||||
// tables
|
||||
tableColumnNames: {},
|
||||
getTableColumnNames: (tableKey) => {
|
||||
return get().tableColumnNames[tableKey] || null;
|
||||
},
|
||||
setTableColumnNames: (tableKey) => (names) => {
|
||||
// Update the table column names for the given table
|
||||
set({
|
||||
tableColumnNames: {
|
||||
...get().tableColumnNames,
|
||||
[tableKey]: names
|
||||
}
|
||||
});
|
||||
},
|
||||
clearTableColumnNames: () => {
|
||||
set({ tableColumnNames: {} });
|
||||
},
|
||||
tableSorting: {},
|
||||
getTableSorting: (tableKey) => {
|
||||
return get().tableSorting[tableKey] || {};
|
||||
},
|
||||
setTableSorting: (tableKey) => (sorting) => {
|
||||
// Update the table sorting for the given table
|
||||
set({
|
||||
tableSorting: {
|
||||
...get().tableSorting,
|
||||
[tableKey]: sorting
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// detail drawers
|
||||
detailDrawerStack: 0,
|
||||
addDetailDrawer: (value) => {
|
||||
|
91
src/frontend/src/states/StoredTableState.tsx
Normal file
91
src/frontend/src/states/StoredTableState.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
import type { DataTableSortStatus } from 'mantine-datatable';
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
const DEFAULT_PAGE_SIZE: number = 25;
|
||||
|
||||
/**
|
||||
* Interfacing for storing persistent table state in the browser.
|
||||
*
|
||||
* The following properties are stored:
|
||||
* - pageSize: The number of rows to display per page in the table.
|
||||
* - hiddenColumns: An array of column names that are hidden in a given table.
|
||||
* - columnNames: An object mapping table keys to arrays of column names.
|
||||
* - sorting: An object mapping table keys to sorting configurations.
|
||||
*/
|
||||
interface StoredTableStateProps {
|
||||
pageSize: number;
|
||||
setPageSize: (size: number) => void;
|
||||
tableSorting: Record<string, any>;
|
||||
getTableSorting: (tableKey: string) => DataTableSortStatus;
|
||||
setTableSorting: (
|
||||
tableKey: string
|
||||
) => (sorting: DataTableSortStatus<any>) => void;
|
||||
tableColumnNames: Record<string, Record<string, string>>;
|
||||
getTableColumnNames: (tableKey: string) => Record<string, string>;
|
||||
setTableColumnNames: (
|
||||
tableKey: string
|
||||
) => (names: Record<string, string>) => void;
|
||||
clearTableColumnNames: () => void;
|
||||
hiddenColumns: Record<string, string[]>;
|
||||
getHiddenColumns: (tableKey: string) => string[] | null;
|
||||
setHiddenColumns: (tableKey: string) => (columns: string[]) => void;
|
||||
}
|
||||
|
||||
export const useStoredTableState = create<StoredTableStateProps>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
pageSize: DEFAULT_PAGE_SIZE,
|
||||
setPageSize: (size: number) => {
|
||||
set((state) => ({
|
||||
pageSize: size
|
||||
}));
|
||||
},
|
||||
tableSorting: {},
|
||||
getTableSorting: (tableKey) => {
|
||||
return get().tableSorting[tableKey] || {};
|
||||
},
|
||||
setTableSorting: (tableKey) => (sorting) => {
|
||||
// Update the table sorting for the given table
|
||||
set({
|
||||
tableSorting: {
|
||||
...get().tableSorting,
|
||||
[tableKey]: sorting
|
||||
}
|
||||
});
|
||||
},
|
||||
tableColumnNames: {},
|
||||
getTableColumnNames: (tableKey) => {
|
||||
return get().tableColumnNames[tableKey] || null;
|
||||
},
|
||||
setTableColumnNames: (tableKey) => (names) => {
|
||||
// Update the table column names for the given table
|
||||
set({
|
||||
tableColumnNames: {
|
||||
...get().tableColumnNames,
|
||||
[tableKey]: names
|
||||
}
|
||||
});
|
||||
},
|
||||
clearTableColumnNames: () => {
|
||||
set({ tableColumnNames: {} });
|
||||
},
|
||||
hiddenColumns: {},
|
||||
getHiddenColumns: (tableKey) => {
|
||||
return get().hiddenColumns?.[tableKey] ?? null;
|
||||
},
|
||||
setHiddenColumns: (tableKey) => (columns) => {
|
||||
// Update the hidden columns for the given table
|
||||
set({
|
||||
hiddenColumns: {
|
||||
...get().hiddenColumns,
|
||||
[tableKey]: columns
|
||||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: 'inventree-table-state'
|
||||
}
|
||||
)
|
||||
);
|
@ -1,10 +1,5 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
Box,
|
||||
LoadingOverlay,
|
||||
type MantineStyleProp,
|
||||
Stack
|
||||
} from '@mantine/core';
|
||||
import { Box, type MantineStyleProp, Stack } from '@mantine/core';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
type ContextMenuItemOptions,
|
||||
@ -35,12 +30,12 @@ import { resolveItem } from '../functions/conversion';
|
||||
import { extractAvailableFields, mapFields } from '../functions/forms';
|
||||
import { showApiErrorMessage } from '../functions/notifications';
|
||||
import { useLocalState } from '../states/LocalState';
|
||||
import { useStoredTableState } from '../states/StoredTableState';
|
||||
import type { TableColumn } from './Column';
|
||||
import InvenTreeTableHeader from './InvenTreeTableHeader';
|
||||
import { type RowAction, RowActions } from './RowActions';
|
||||
|
||||
const ACTIONS_COLUMN_ACCESSOR: string = '--actions--';
|
||||
const defaultPageSize: number = 25;
|
||||
const PAGE_SIZES = [10, 15, 20, 25, 50, 100, 500];
|
||||
|
||||
/**
|
||||
@ -140,13 +135,18 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
columns: TableColumn<T>[];
|
||||
props: InvenTreeTableProps<T>;
|
||||
}>) {
|
||||
const { userTheme } = useLocalState();
|
||||
|
||||
const {
|
||||
pageSize,
|
||||
setPageSize,
|
||||
getHiddenColumns,
|
||||
setHiddenColumns,
|
||||
getTableColumnNames,
|
||||
setTableColumnNames,
|
||||
getTableSorting,
|
||||
setTableSorting,
|
||||
userTheme
|
||||
} = useLocalState();
|
||||
setTableSorting
|
||||
} = useStoredTableState();
|
||||
|
||||
const [fieldNames, setFieldNames] = useState<Record<string, string>>({});
|
||||
|
||||
@ -191,7 +191,7 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
|
||||
// Request OPTIONS data from the API, before we load the table
|
||||
const tableOptionQuery = useQuery({
|
||||
enabled: !!url && !tableData && tableState.storedDataLoaded,
|
||||
enabled: !!url && !tableData,
|
||||
queryKey: [
|
||||
'options',
|
||||
url,
|
||||
@ -274,30 +274,6 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
return tableProps.enableSelection || tableProps.enableBulkDelete || false;
|
||||
}, [tableProps]);
|
||||
|
||||
useEffect(() => {
|
||||
// On first table render, "hide" any default hidden columns
|
||||
if (tableProps.enableColumnSwitching == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// A "null" value indicates that the initial "hidden" columns have not been set
|
||||
if (tableState.storedDataLoaded && tableState.hiddenColumns == null) {
|
||||
const columnNames: string[] = columns
|
||||
.filter((col) => {
|
||||
// Find any switchable columns which are hidden by default
|
||||
return col.switchable != false && col.defaultVisible == false;
|
||||
})
|
||||
.map((col) => col.accessor);
|
||||
|
||||
tableState.setHiddenColumns(columnNames);
|
||||
}
|
||||
}, [
|
||||
columns,
|
||||
tableProps.enableColumnSwitching,
|
||||
tableState.hiddenColumns,
|
||||
tableState.storedDataLoaded
|
||||
]);
|
||||
|
||||
// Check if any columns are switchable (can be hidden)
|
||||
const hasSwitchableColumns: boolean = useMemo(() => {
|
||||
if (props.enableColumnSwitching == false) {
|
||||
@ -327,10 +303,6 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
const dataColumns: any = useMemo(() => {
|
||||
let cols: TableColumn[] = columns.filter((col) => col?.hidden != true);
|
||||
|
||||
if (!tableState.storedDataLoaded) {
|
||||
cols = cols.filter((col) => col?.defaultVisible != false);
|
||||
}
|
||||
|
||||
cols = cols.map((col) => {
|
||||
// If the column is *not* switchable, it is always visible
|
||||
// Otherwise, check if it is "default hidden"
|
||||
@ -373,24 +345,29 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
fieldNames,
|
||||
tableProps.rowActions,
|
||||
tableState.hiddenColumns,
|
||||
tableState.selectedRecords,
|
||||
tableState.storedDataLoaded
|
||||
tableState.selectedRecords
|
||||
]);
|
||||
|
||||
// Callback when column visibility is toggled
|
||||
function toggleColumn(columnName: string) {
|
||||
const newColumns = [...dataColumns];
|
||||
const toggleColumn = useCallback(
|
||||
(columnName: string) => {
|
||||
const newColumns = [...dataColumns];
|
||||
|
||||
const colIdx = newColumns.findIndex((col) => col.accessor == columnName);
|
||||
const colIdx = newColumns.findIndex((col) => col.accessor == columnName);
|
||||
|
||||
if (colIdx >= 0 && colIdx < newColumns.length) {
|
||||
newColumns[colIdx].hidden = !newColumns[colIdx].hidden;
|
||||
}
|
||||
if (colIdx >= 0 && colIdx < newColumns.length) {
|
||||
newColumns[colIdx].hidden = !newColumns[colIdx].hidden;
|
||||
}
|
||||
|
||||
tableState.setHiddenColumns(
|
||||
newColumns.filter((col) => col.hidden).map((col) => col.accessor)
|
||||
);
|
||||
}
|
||||
const hiddenColumns = newColumns
|
||||
.filter((col) => col.hidden)
|
||||
.map((col) => col.accessor);
|
||||
|
||||
tableState.setHiddenColumns(hiddenColumns);
|
||||
setHiddenColumns(cacheKey)(hiddenColumns);
|
||||
},
|
||||
[cacheKey, dataColumns]
|
||||
);
|
||||
|
||||
// Final state of the table columns
|
||||
const tableColumns = useDataTableColumns({
|
||||
@ -456,8 +433,6 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
|
||||
// Pagination
|
||||
if (tableProps.enablePagination && paginate) {
|
||||
const pageSize = tableState.pageSize ?? defaultPageSize;
|
||||
if (pageSize != tableState.pageSize) tableState.setPageSize(pageSize);
|
||||
queryParams.limit = pageSize;
|
||||
queryParams.offset = (tableState.page - 1) * pageSize;
|
||||
}
|
||||
@ -476,30 +451,44 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
return queryParams;
|
||||
},
|
||||
[
|
||||
sortStatus,
|
||||
tableProps.params,
|
||||
tableProps.enablePagination,
|
||||
tableState.filterSet.activeFilters,
|
||||
tableState.queryFilters,
|
||||
tableState.searchTerm,
|
||||
tableState.pageSize,
|
||||
tableState.setPageSize,
|
||||
sortStatus,
|
||||
getOrderingTerm
|
||||
]
|
||||
);
|
||||
|
||||
const [sortingLoaded, setSortingLoaded] = useState<boolean>(false);
|
||||
const [cacheLoaded, setCacheLoaded] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const tableKey: string = tableState.tableKey.split('-')[0];
|
||||
const sorting: DataTableSortStatus = getTableSorting(tableKey);
|
||||
const sorting: DataTableSortStatus = getTableSorting(cacheKey);
|
||||
|
||||
if (sorting && !!sorting.columnAccessor && !!sorting.direction) {
|
||||
setSortStatus(sorting);
|
||||
}
|
||||
|
||||
setSortingLoaded(true);
|
||||
}, []);
|
||||
const hiddenColumns = getHiddenColumns(cacheKey);
|
||||
|
||||
if (hiddenColumns == null) {
|
||||
// A "null" value indicates that the initial "hidden" columns have not been set
|
||||
const columnNames: string[] = columns
|
||||
.filter((col) => {
|
||||
// Find any switchable columns which are hidden by default
|
||||
return col.switchable != false && col.defaultVisible == false;
|
||||
})
|
||||
.map((col) => col.accessor);
|
||||
|
||||
setHiddenColumns(cacheKey)(columnNames);
|
||||
tableState.setHiddenColumns(columnNames);
|
||||
} else {
|
||||
tableState.setHiddenColumns(hiddenColumns);
|
||||
}
|
||||
|
||||
setCacheLoaded(true);
|
||||
}, [cacheKey]);
|
||||
|
||||
// Return the ordering parameter
|
||||
function getOrderingTerm() {
|
||||
@ -521,13 +510,15 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
tableProps.noRecordsText ?? t`No records found`
|
||||
);
|
||||
|
||||
const handleSortStatusChange = (status: DataTableSortStatus<T>) => {
|
||||
tableState.setPage(1);
|
||||
setSortStatus(status);
|
||||
const handleSortStatusChange = useCallback(
|
||||
(status: DataTableSortStatus<T>) => {
|
||||
tableState.setPage(1);
|
||||
setSortStatus(status);
|
||||
|
||||
const tableKey = tableState.tableKey.split('-')[0];
|
||||
setTableSorting(tableKey)(status);
|
||||
};
|
||||
setTableSorting(cacheKey)(status);
|
||||
},
|
||||
[cacheKey]
|
||||
);
|
||||
|
||||
// Function to perform API query to fetch required data
|
||||
const fetchTableData = async () => {
|
||||
@ -538,16 +529,11 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!sortingLoaded) {
|
||||
if (!cacheLoaded) {
|
||||
// Sorting not yet loaded - do not load!
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!tableState.storedDataLoaded) {
|
||||
// Table data not yet loaded - do not load!
|
||||
return [];
|
||||
}
|
||||
|
||||
return api
|
||||
.get(url, {
|
||||
params: queryParams,
|
||||
@ -581,15 +567,13 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
queryKey: [
|
||||
'tabledata',
|
||||
url,
|
||||
tableState.tableKey,
|
||||
tableState.page,
|
||||
props.params,
|
||||
sortingLoaded,
|
||||
cacheLoaded,
|
||||
sortStatus.columnAccessor,
|
||||
sortStatus.direction,
|
||||
tableState.tableKey,
|
||||
tableState.filterSet.activeFilters,
|
||||
tableState.storedDataLoaded,
|
||||
tableState.searchTerm
|
||||
],
|
||||
retry: 5,
|
||||
@ -602,7 +586,7 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
|
||||
return true;
|
||||
},
|
||||
enabled: !!url && !tableData && tableState.storedDataLoaded,
|
||||
enabled: !!url && !tableData,
|
||||
queryFn: fetchTableData
|
||||
});
|
||||
|
||||
@ -629,16 +613,17 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
tableState.isLoading
|
||||
]);
|
||||
|
||||
const tablePageSize = useMemo(() => {
|
||||
if (tableProps.enablePagination != false) {
|
||||
return pageSize;
|
||||
} else {
|
||||
return tableState.recordCount;
|
||||
}
|
||||
}, [tableProps.enablePagination, pageSize, tableState.recordCount]);
|
||||
|
||||
// Update tableState.records when new data received
|
||||
useEffect(() => {
|
||||
const data = tableData ?? apiData ?? [];
|
||||
|
||||
tableState.setRecords(data);
|
||||
|
||||
// set pagesize to length if pagination is disabled
|
||||
if (!tableProps.enablePagination) {
|
||||
tableState.setPageSize(data?.length ?? defaultPageSize);
|
||||
}
|
||||
tableState.setRecords(tableData ?? apiData ?? []);
|
||||
}, [tableData, apiData]);
|
||||
|
||||
// Callback when a cell is clicked
|
||||
@ -735,12 +720,12 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
return showContextMenu(items)(event);
|
||||
};
|
||||
|
||||
// pagination refresh table if pageSize changes
|
||||
function updatePageSize(newData: number) {
|
||||
tableState.setPageSize(newData);
|
||||
// Pagination refresh table if pageSize changes
|
||||
const updatePageSize = useCallback((size: number) => {
|
||||
setPageSize(size);
|
||||
tableState.setPage(1);
|
||||
tableState.refreshTable();
|
||||
}
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Memoize row expansion options:
|
||||
@ -776,7 +761,7 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
_params = {
|
||||
..._params,
|
||||
totalRecords: tableState.recordCount,
|
||||
recordsPerPage: tableState.pageSize,
|
||||
recordsPerPage: tablePageSize,
|
||||
page: tableState.page,
|
||||
onPageChange: tableState.setPage,
|
||||
recordsPerPageOptions: PAGE_SIZES,
|
||||
@ -786,9 +771,9 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
|
||||
return _params;
|
||||
}, [
|
||||
tablePageSize,
|
||||
tableProps.enablePagination,
|
||||
tableState.recordCount,
|
||||
tableState.pageSize,
|
||||
tableState.page,
|
||||
tableState.setPage,
|
||||
updatePageSize
|
||||
@ -806,7 +791,7 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
<>
|
||||
<Stack gap='xs'>
|
||||
{!tableProps.noHeader && (
|
||||
<Boundary label={`InvenTreeTableHeader-${tableState.tableKey}`}>
|
||||
<Boundary label={`InvenTreeTableHeader-${cacheKey}`}>
|
||||
<InvenTreeTableHeader
|
||||
tableUrl={url}
|
||||
tableState={tableState}
|
||||
@ -818,9 +803,8 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
||||
/>
|
||||
</Boundary>
|
||||
)}
|
||||
<Boundary label={`InvenTreeTable-${tableState.tableKey}`}>
|
||||
<Boundary label={`InvenTreeTable-${cacheKey}`}>
|
||||
<Box pos='relative'>
|
||||
<LoadingOverlay visible={!tableState.storedDataLoaded} />
|
||||
<DataTable
|
||||
withTableBorder={!tableProps.noHeader}
|
||||
withColumnBorders
|
||||
|
Reference in New Issue
Block a user