2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-01-28 09:03:41 +00:00

[UI] Bug fix for table column reordering (#11131)

* [UI] Bug fix for table column reordering

- Ref: https://github.com/icflorescu/mantine-datatable/issues/759
- Adds hash to column cache key based on provided columns
- Prevent infinite loop for react hooks

* Remove previous cache approach

* Remove unused code
This commit is contained in:
Oliver
2026-01-14 10:44:27 +11:00
committed by GitHub
parent f2cef4f266
commit 76cfb442a4
3 changed files with 24 additions and 21 deletions

View File

@@ -24,3 +24,15 @@ export function shortenString({
return `${str.slice(0, N)} ... ${str.slice(-N)}`;
}
/**
* Generate a short hash from a long string
*/
export function hashString(str: string): string {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = (hash << 5) - hash + str.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return hash.toString(36);
}

View File

@@ -29,6 +29,7 @@ import { Boundary } from '../components/Boundary';
import { useApi } from '../contexts/ApiContext';
import { extractAvailableFields, mapFields } from '../functions/forms';
import { showApiErrorMessage } from '../functions/notifications';
import { hashString } from '../functions/tables';
import { useLocalState } from '../states/LocalState';
import { useUserSettingsState } from '../states/SettingsStates';
import { useStoredTableState } from '../states/StoredTableState';
@@ -101,7 +102,7 @@ export function InvenTreeTable<T extends Record<string, any>>({
// Key used for caching table data
const cacheKey = useMemo(() => {
const key: string = `table-${tableState.tableKey}`;
const key: string = `tbl-${tableState.tableKey}`;
// Remove anything after (and including) "mantine"
const mantineIndex = key.indexOf('-mantine');
@@ -244,6 +245,12 @@ export function InvenTreeTable<T extends Record<string, any>>({
[tableState.setSelectedRecords]
);
// A hash of the current column configuration
// This is a workaround to fix an issue with mantine-datatable where
// the columns do not update correctly when they are changed dynamically
// Ref: https://github.com/icflorescu/mantine-datatable/issues/759
const [columnHash, setColumnHash] = useState<string>('');
// Update column visibility when hiddenColumns change
const dataColumns: any = useMemo(() => {
let cols: TableColumn[] = columns.filter((col) => col?.hidden != true);
@@ -296,6 +303,9 @@ export function InvenTreeTable<T extends Record<string, any>>({
});
}
const columnNames: string = cols.map((col) => col.accessor).join(',');
setColumnHash(hashString(columnNames));
return cols;
}, [
columns,
@@ -328,28 +338,11 @@ export function InvenTreeTable<T extends Record<string, any>>({
// Final state of the table columns
const tableColumns = useDataTableColumns({
key: cacheKey,
key: `${cacheKey}-${columnHash}`,
columns: dataColumns,
getInitialValueInEffect: false
});
// Cache the "ordering" of the columns
const dataColumnsOrder: string[] = useMemo(() => {
return dataColumns.map((col: any) => col.accessor);
}, [dataColumns]);
// Ensure that the "actions" column is always at the end of the list
// This effect is necessary as sometimes the underlying mantine-datatable columns change
useEffect(() => {
// Update the columns order only if it has changed
if (
JSON.stringify(tableColumns.columnsOrder) !=
JSON.stringify(dataColumnsOrder)
) {
tableColumns.setColumnsOrder(dataColumnsOrder);
}
}, [cacheKey, dataColumnsOrder]);
// Reset the pagination state when the search term changes
useEffect(() => {
tableState.setPage(1);

View File

@@ -18,7 +18,6 @@ import {
} from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ActionButton } from '@lib/components/ActionButton';
import { AddItemButton } from '@lib/components/AddItemButton';
@@ -151,7 +150,6 @@ export default function BuildOutputTable({
}: Readonly<{ build: any; refreshBuild: () => void }>) {
const api = useApi();
const user = useUserState();
const navigate = useNavigate();
const table = useTable('build-outputs');
const buildId: number = useMemo(() => {