diff --git a/src/frontend/src/components/tables/InvenTreeTable.tsx b/src/frontend/src/components/tables/InvenTreeTable.tsx index ca17406fef..41c506a3c5 100644 --- a/src/frontend/src/components/tables/InvenTreeTable.tsx +++ b/src/frontend/src/components/tables/InvenTreeTable.tsx @@ -1,12 +1,11 @@ import { t } from '@lingui/macro'; import { ActionIcon, Indicator, Space, Stack, Tooltip } from '@mantine/core'; import { Group } from '@mantine/core'; -import { useLocalStorage } from '@mantine/hooks'; import { IconFilter, IconRefresh } from '@tabler/icons-react'; import { IconBarcode, IconPrinter } from '@tabler/icons-react'; import { useQuery } from '@tanstack/react-query'; 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 { TableState } from '../../hooks/UseTable'; @@ -100,12 +99,6 @@ export function InvenTreeTable({ columns: TableColumn[]; props: InvenTreeTableProps; }) { - // 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) const tableProps: InvenTreeTableProps = useMemo(() => { return { @@ -119,18 +112,9 @@ export function InvenTreeTable({ (col: TableColumn) => col.switchable ?? true ); - // A list of hidden columns, saved to local storage - const [hiddenColumns, setHiddenColumns] = useLocalStorage({ - key: `inventree-hidden-table-columns-${tableName}`, - defaultValue: [] - }); - - // Data selection - const [selectedRecords, setSelectedRecords] = useState([]); - - function onSelectedRecordsChange(records: any[]) { - setSelectedRecords(records); - } + const onSelectedRecordsChange = useCallback((records: any[]) => { + tableState.setSelectedRecords(records); + }, []); // Update column visibility when hiddenColumns change const dataColumns: any = useMemo(() => { @@ -138,7 +122,7 @@ export function InvenTreeTable({ let hidden: boolean = col.hidden ?? false; if (col.switchable ?? true) { - hidden = hiddenColumns.includes(col.accessor); + hidden = tableState.hiddenColumns.includes(col.accessor); } return { @@ -159,7 +143,7 @@ export function InvenTreeTable({ return ( 0} + disabled={tableState.selectedRecords.length > 0} /> ); } @@ -169,10 +153,10 @@ export function InvenTreeTable({ return cols; }, [ columns, - hiddenColumns, tableProps.rowActions, tableProps.enableSelection, - selectedRecords + tableState.hiddenColumns, + tableState.selectedRecords ]); // Callback when column visibility is toggled @@ -185,7 +169,7 @@ export function InvenTreeTable({ newColumns[colIdx].hidden = !newColumns[colIdx].hidden; } - setHiddenColumns( + tableState.setHiddenColumns( newColumns.filter((col) => col.hidden).map((col) => col.accessor) ); } @@ -196,13 +180,10 @@ export function InvenTreeTable({ // Filter list visibility const [filtersVisible, setFiltersVisible] = useState(false); - // Search term - const [searchTerm, setSearchTerm] = useState(''); - // Reset the pagination state when the search term changes useEffect(() => { setPage(1); - }, [searchTerm]); + }, [tableState.searchTerm]); /* * Construct query filters for the current table @@ -218,8 +199,8 @@ export function InvenTreeTable({ ); // Add custom search term - if (searchTerm) { - queryParams.search = searchTerm; + if (tableState.searchTerm) { + queryParams.search = tableState.searchTerm; } // Pagination @@ -340,7 +321,7 @@ export function InvenTreeTable({ default: setMissingRecordsText( t`Unknown error` + ': ' + response.statusText - ); // TODO: Translate + ); break; } @@ -352,15 +333,15 @@ export function InvenTreeTable({ }); }; - const { data, isError, isFetching, isLoading, refetch } = useQuery({ + const { data, isFetching, refetch } = useQuery({ queryKey: [ - tableState.tableKey, + page, props.params, sortStatus.columnAccessor, sortStatus.direction, - page, + tableState.tableKey, tableState.activeFilters, - searchTerm + tableState.searchTerm ], queryFn: fetchTableData, refetchOnWindowFocus: false, @@ -409,7 +390,9 @@ export function InvenTreeTable({ {tableProps.enableSearch && ( setSearchTerm(term)} + searchCallback={(term: string) => + tableState.setSearchTerm(term) + } /> )} {tableProps.enableRefresh && ( @@ -464,7 +447,7 @@ export function InvenTreeTable({ sortStatus={sortStatus} onSortStatusChange={handleSortStatusChange} selectedRecords={ - tableProps.enableSelection ? selectedRecords : undefined + tableProps.enableSelection ? tableState.selectedRecords : undefined } onSelectedRecordsChange={ tableProps.enableSelection ? onSelectedRecordsChange : undefined diff --git a/src/frontend/src/hooks/UseTable.tsx b/src/frontend/src/hooks/UseTable.tsx index b4fb340ef6..15efe7ca3a 100644 --- a/src/frontend/src/hooks/UseTable.tsx +++ b/src/frontend/src/hooks/UseTable.tsx @@ -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. * refreshTable: A callback function to externally refresh the table. * 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 = { tableKey: string; + refreshTable: () => void; activeFilters: TableFilter[]; setActiveFilters: (filters: TableFilter[]) => 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([]); }, []); + // Array of selected records + const [selectedRecords, setSelectedRecords] = useState([]); + + const clearSelectedRecords = useCallback(() => { + setSelectedRecords([]); + }, []); + + // A list of hidden columns, saved to local storage + const [hiddenColumns, setHiddenColumns] = useLocalStorage({ + key: `inventree-hidden-table-columns-${tableName}`, + defaultValue: [] + }); + + // Search term + const [searchTerm, setSearchTerm] = useState(''); + return { tableKey, + refreshTable, activeFilters, setActiveFilters, clearActiveFilters, - refreshTable + selectedRecords, + setSelectedRecords, + clearSelectedRecords, + hiddenColumns, + setHiddenColumns, + searchTerm, + setSearchTerm }; }