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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
Reference in New Issue
Block a user