mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +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:
		| @@ -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<T = any>({ | ||||
|   columns: TableColumn<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) | ||||
|   const tableProps: InvenTreeTableProps<T> = useMemo(() => { | ||||
|     return { | ||||
| @@ -119,18 +112,9 @@ export function InvenTreeTable<T = any>({ | ||||
|     (col: TableColumn) => col.switchable ?? true | ||||
|   ); | ||||
|  | ||||
|   // A list of hidden columns, saved to local storage | ||||
|   const [hiddenColumns, setHiddenColumns] = useLocalStorage<string[]>({ | ||||
|     key: `inventree-hidden-table-columns-${tableName}`, | ||||
|     defaultValue: [] | ||||
|   }); | ||||
|  | ||||
|   // Data selection | ||||
|   const [selectedRecords, setSelectedRecords] = useState<any[]>([]); | ||||
|  | ||||
|   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<T = any>({ | ||||
|       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<T = any>({ | ||||
|           return ( | ||||
|             <RowActions | ||||
|               actions={tableProps.rowActions?.(record) ?? []} | ||||
|               disabled={selectedRecords.length > 0} | ||||
|               disabled={tableState.selectedRecords.length > 0} | ||||
|             /> | ||||
|           ); | ||||
|         } | ||||
| @@ -169,10 +153,10 @@ export function InvenTreeTable<T = any>({ | ||||
|     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<T = any>({ | ||||
|       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<T = any>({ | ||||
|   // Filter list visibility | ||||
|   const [filtersVisible, setFiltersVisible] = useState<boolean>(false); | ||||
|  | ||||
|   // Search term | ||||
|   const [searchTerm, setSearchTerm] = useState<string>(''); | ||||
|  | ||||
|   // 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<T = any>({ | ||||
|     ); | ||||
|  | ||||
|     // Add custom search term | ||||
|     if (searchTerm) { | ||||
|       queryParams.search = searchTerm; | ||||
|     if (tableState.searchTerm) { | ||||
|       queryParams.search = tableState.searchTerm; | ||||
|     } | ||||
|  | ||||
|     // Pagination | ||||
| @@ -340,7 +321,7 @@ export function InvenTreeTable<T = any>({ | ||||
|           default: | ||||
|             setMissingRecordsText( | ||||
|               t`Unknown error` + ': ' + response.statusText | ||||
|             ); // TODO: Translate | ||||
|             ); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
| @@ -352,15 +333,15 @@ export function InvenTreeTable<T = any>({ | ||||
|       }); | ||||
|   }; | ||||
|  | ||||
|   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<T = any>({ | ||||
|           <Group position="right" spacing={5}> | ||||
|             {tableProps.enableSearch && ( | ||||
|               <TableSearchInput | ||||
|                 searchCallback={(term: string) => setSearchTerm(term)} | ||||
|                 searchCallback={(term: string) => | ||||
|                   tableState.setSearchTerm(term) | ||||
|                 } | ||||
|               /> | ||||
|             )} | ||||
|             {tableProps.enableRefresh && ( | ||||
| @@ -464,7 +447,7 @@ export function InvenTreeTable<T = any>({ | ||||
|           sortStatus={sortStatus} | ||||
|           onSortStatusChange={handleSortStatusChange} | ||||
|           selectedRecords={ | ||||
|             tableProps.enableSelection ? selectedRecords : undefined | ||||
|             tableProps.enableSelection ? tableState.selectedRecords : undefined | ||||
|           } | ||||
|           onSelectedRecordsChange={ | ||||
|             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. | ||||
|  * 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<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 { | ||||
|     tableKey, | ||||
|     refreshTable, | ||||
|     activeFilters, | ||||
|     setActiveFilters, | ||||
|     clearActiveFilters, | ||||
|     refreshTable | ||||
|     selectedRecords, | ||||
|     setSelectedRecords, | ||||
|     clearSelectedRecords, | ||||
|     hiddenColumns, | ||||
|     setHiddenColumns, | ||||
|     searchTerm, | ||||
|     setSearchTerm | ||||
|   }; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user