mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Table Hook Updates (#6093)
* Update useTable hook - Storage for "selected rows" - Aim is to make row selection available outside table component * Use updated hook to manage row selection * Add more table data to useTable: - hidden column selection - search terms * Remove unused import * Remove unused function * Cleanup
This commit is contained in:
parent
72167630ac
commit
64671dce20
@ -1,12 +1,11 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { ActionIcon, Indicator, Space, Stack, Tooltip } from '@mantine/core';
|
import { ActionIcon, Indicator, Space, Stack, Tooltip } from '@mantine/core';
|
||||||
import { Group } from '@mantine/core';
|
import { Group } from '@mantine/core';
|
||||||
import { useLocalStorage } from '@mantine/hooks';
|
|
||||||
import { IconFilter, IconRefresh } from '@tabler/icons-react';
|
import { IconFilter, IconRefresh } from '@tabler/icons-react';
|
||||||
import { IconBarcode, IconPrinter } from '@tabler/icons-react';
|
import { IconBarcode, IconPrinter } from '@tabler/icons-react';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { DataTable, DataTableSortStatus } from 'mantine-datatable';
|
import { DataTable, DataTableSortStatus } from 'mantine-datatable';
|
||||||
import { Fragment, useEffect, useMemo, useState } from 'react';
|
import { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { api } from '../../App';
|
import { api } from '../../App';
|
||||||
import { TableState } from '../../hooks/UseTable';
|
import { TableState } from '../../hooks/UseTable';
|
||||||
@ -100,12 +99,6 @@ export function InvenTreeTable<T = any>({
|
|||||||
columns: TableColumn<T>[];
|
columns: TableColumn<T>[];
|
||||||
props: InvenTreeTableProps<T>;
|
props: InvenTreeTableProps<T>;
|
||||||
}) {
|
}) {
|
||||||
// Use the first part of the table key as the table name
|
|
||||||
const tableName: string = useMemo(() => {
|
|
||||||
let key = tableState?.tableKey ?? 'table';
|
|
||||||
return key.split('-')[0];
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Build table properties based on provided props (and default props)
|
// Build table properties based on provided props (and default props)
|
||||||
const tableProps: InvenTreeTableProps<T> = useMemo(() => {
|
const tableProps: InvenTreeTableProps<T> = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
@ -119,18 +112,9 @@ export function InvenTreeTable<T = any>({
|
|||||||
(col: TableColumn) => col.switchable ?? true
|
(col: TableColumn) => col.switchable ?? true
|
||||||
);
|
);
|
||||||
|
|
||||||
// A list of hidden columns, saved to local storage
|
const onSelectedRecordsChange = useCallback((records: any[]) => {
|
||||||
const [hiddenColumns, setHiddenColumns] = useLocalStorage<string[]>({
|
tableState.setSelectedRecords(records);
|
||||||
key: `inventree-hidden-table-columns-${tableName}`,
|
}, []);
|
||||||
defaultValue: []
|
|
||||||
});
|
|
||||||
|
|
||||||
// Data selection
|
|
||||||
const [selectedRecords, setSelectedRecords] = useState<any[]>([]);
|
|
||||||
|
|
||||||
function onSelectedRecordsChange(records: any[]) {
|
|
||||||
setSelectedRecords(records);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update column visibility when hiddenColumns change
|
// Update column visibility when hiddenColumns change
|
||||||
const dataColumns: any = useMemo(() => {
|
const dataColumns: any = useMemo(() => {
|
||||||
@ -138,7 +122,7 @@ export function InvenTreeTable<T = any>({
|
|||||||
let hidden: boolean = col.hidden ?? false;
|
let hidden: boolean = col.hidden ?? false;
|
||||||
|
|
||||||
if (col.switchable ?? true) {
|
if (col.switchable ?? true) {
|
||||||
hidden = hiddenColumns.includes(col.accessor);
|
hidden = tableState.hiddenColumns.includes(col.accessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -159,7 +143,7 @@ export function InvenTreeTable<T = any>({
|
|||||||
return (
|
return (
|
||||||
<RowActions
|
<RowActions
|
||||||
actions={tableProps.rowActions?.(record) ?? []}
|
actions={tableProps.rowActions?.(record) ?? []}
|
||||||
disabled={selectedRecords.length > 0}
|
disabled={tableState.selectedRecords.length > 0}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -169,10 +153,10 @@ export function InvenTreeTable<T = any>({
|
|||||||
return cols;
|
return cols;
|
||||||
}, [
|
}, [
|
||||||
columns,
|
columns,
|
||||||
hiddenColumns,
|
|
||||||
tableProps.rowActions,
|
tableProps.rowActions,
|
||||||
tableProps.enableSelection,
|
tableProps.enableSelection,
|
||||||
selectedRecords
|
tableState.hiddenColumns,
|
||||||
|
tableState.selectedRecords
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Callback when column visibility is toggled
|
// Callback when column visibility is toggled
|
||||||
@ -185,7 +169,7 @@ export function InvenTreeTable<T = any>({
|
|||||||
newColumns[colIdx].hidden = !newColumns[colIdx].hidden;
|
newColumns[colIdx].hidden = !newColumns[colIdx].hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
setHiddenColumns(
|
tableState.setHiddenColumns(
|
||||||
newColumns.filter((col) => col.hidden).map((col) => col.accessor)
|
newColumns.filter((col) => col.hidden).map((col) => col.accessor)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -196,13 +180,10 @@ export function InvenTreeTable<T = any>({
|
|||||||
// Filter list visibility
|
// Filter list visibility
|
||||||
const [filtersVisible, setFiltersVisible] = useState<boolean>(false);
|
const [filtersVisible, setFiltersVisible] = useState<boolean>(false);
|
||||||
|
|
||||||
// Search term
|
|
||||||
const [searchTerm, setSearchTerm] = useState<string>('');
|
|
||||||
|
|
||||||
// Reset the pagination state when the search term changes
|
// Reset the pagination state when the search term changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPage(1);
|
setPage(1);
|
||||||
}, [searchTerm]);
|
}, [tableState.searchTerm]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct query filters for the current table
|
* Construct query filters for the current table
|
||||||
@ -218,8 +199,8 @@ export function InvenTreeTable<T = any>({
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add custom search term
|
// Add custom search term
|
||||||
if (searchTerm) {
|
if (tableState.searchTerm) {
|
||||||
queryParams.search = searchTerm;
|
queryParams.search = tableState.searchTerm;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pagination
|
// Pagination
|
||||||
@ -340,7 +321,7 @@ export function InvenTreeTable<T = any>({
|
|||||||
default:
|
default:
|
||||||
setMissingRecordsText(
|
setMissingRecordsText(
|
||||||
t`Unknown error` + ': ' + response.statusText
|
t`Unknown error` + ': ' + response.statusText
|
||||||
); // TODO: Translate
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,15 +333,15 @@ export function InvenTreeTable<T = any>({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data, isError, isFetching, isLoading, refetch } = useQuery({
|
const { data, isFetching, refetch } = useQuery({
|
||||||
queryKey: [
|
queryKey: [
|
||||||
tableState.tableKey,
|
page,
|
||||||
props.params,
|
props.params,
|
||||||
sortStatus.columnAccessor,
|
sortStatus.columnAccessor,
|
||||||
sortStatus.direction,
|
sortStatus.direction,
|
||||||
page,
|
tableState.tableKey,
|
||||||
tableState.activeFilters,
|
tableState.activeFilters,
|
||||||
searchTerm
|
tableState.searchTerm
|
||||||
],
|
],
|
||||||
queryFn: fetchTableData,
|
queryFn: fetchTableData,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
@ -409,7 +390,9 @@ export function InvenTreeTable<T = any>({
|
|||||||
<Group position="right" spacing={5}>
|
<Group position="right" spacing={5}>
|
||||||
{tableProps.enableSearch && (
|
{tableProps.enableSearch && (
|
||||||
<TableSearchInput
|
<TableSearchInput
|
||||||
searchCallback={(term: string) => setSearchTerm(term)}
|
searchCallback={(term: string) =>
|
||||||
|
tableState.setSearchTerm(term)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{tableProps.enableRefresh && (
|
{tableProps.enableRefresh && (
|
||||||
@ -464,7 +447,7 @@ export function InvenTreeTable<T = any>({
|
|||||||
sortStatus={sortStatus}
|
sortStatus={sortStatus}
|
||||||
onSortStatusChange={handleSortStatusChange}
|
onSortStatusChange={handleSortStatusChange}
|
||||||
selectedRecords={
|
selectedRecords={
|
||||||
tableProps.enableSelection ? selectedRecords : undefined
|
tableProps.enableSelection ? tableState.selectedRecords : undefined
|
||||||
}
|
}
|
||||||
onSelectedRecordsChange={
|
onSelectedRecordsChange={
|
||||||
tableProps.enableSelection ? onSelectedRecordsChange : undefined
|
tableProps.enableSelection ? onSelectedRecordsChange : undefined
|
||||||
|
@ -9,13 +9,23 @@ import { TableFilter } from '../components/tables/Filter';
|
|||||||
* tableKey: A unique key for the table. When this key changes, the table will be refreshed.
|
* tableKey: A unique key for the table. When this key changes, the table will be refreshed.
|
||||||
* refreshTable: A callback function to externally refresh the table.
|
* refreshTable: A callback function to externally refresh the table.
|
||||||
* activeFilters: An array of active filters (saved to local storage)
|
* activeFilters: An array of active filters (saved to local storage)
|
||||||
|
* selectedRecords: An array of selected records (rows) in the table
|
||||||
|
* hiddenColumns: An array of hidden column names
|
||||||
|
* searchTerm: The current search term for the table
|
||||||
*/
|
*/
|
||||||
export type TableState = {
|
export type TableState = {
|
||||||
tableKey: string;
|
tableKey: string;
|
||||||
|
refreshTable: () => void;
|
||||||
activeFilters: TableFilter[];
|
activeFilters: TableFilter[];
|
||||||
setActiveFilters: (filters: TableFilter[]) => void;
|
setActiveFilters: (filters: TableFilter[]) => void;
|
||||||
clearActiveFilters: () => void;
|
clearActiveFilters: () => void;
|
||||||
refreshTable: () => void;
|
selectedRecords: any[];
|
||||||
|
setSelectedRecords: (records: any[]) => void;
|
||||||
|
clearSelectedRecords: () => void;
|
||||||
|
hiddenColumns: string[];
|
||||||
|
setHiddenColumns: (columns: string[]) => void;
|
||||||
|
searchTerm: string;
|
||||||
|
setSearchTerm: (term: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,11 +59,34 @@ export function useTable(tableName: string): TableState {
|
|||||||
setActiveFilters([]);
|
setActiveFilters([]);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Array of selected records
|
||||||
|
const [selectedRecords, setSelectedRecords] = useState<any[]>([]);
|
||||||
|
|
||||||
|
const clearSelectedRecords = useCallback(() => {
|
||||||
|
setSelectedRecords([]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// A list of hidden columns, saved to local storage
|
||||||
|
const [hiddenColumns, setHiddenColumns] = useLocalStorage<string[]>({
|
||||||
|
key: `inventree-hidden-table-columns-${tableName}`,
|
||||||
|
defaultValue: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// Search term
|
||||||
|
const [searchTerm, setSearchTerm] = useState<string>('');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tableKey,
|
tableKey,
|
||||||
|
refreshTable,
|
||||||
activeFilters,
|
activeFilters,
|
||||||
setActiveFilters,
|
setActiveFilters,
|
||||||
clearActiveFilters,
|
clearActiveFilters,
|
||||||
refreshTable
|
selectedRecords,
|
||||||
|
setSelectedRecords,
|
||||||
|
clearSelectedRecords,
|
||||||
|
hiddenColumns,
|
||||||
|
setHiddenColumns,
|
||||||
|
searchTerm,
|
||||||
|
setSearchTerm
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user