Skip to content

Commit

Permalink
fix(DatagridConfigurable): better detect and handle columns changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Quentin Decré committed Aug 26, 2024
1 parent 6472e3a commit 344746a
Showing 1 changed file with 83 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react';
import {
useResourceContext,
usePreference,
useResourceContext,
useStore,
useTranslate,
} from 'ra-core';
import * as React from 'react';

import { Configurable } from '../../preferences';
import { Datagrid, DatagridProps } from './Datagrid';
Expand Down Expand Up @@ -50,6 +50,11 @@ export const DatagridConfigurable = ({
ConfigurableDatagridColumn[]
>(`preferences.${finalPreferenceKey}.availableColumns`, []);

const [columns, setColumns] = useStore<string[]>(
`preferences.${finalPreferenceKey}.columns`,
[]
);

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, setOmit] = useStore<string[] | undefined>(
`preferences.${finalPreferenceKey}.omit`,
Expand All @@ -58,7 +63,7 @@ export const DatagridConfigurable = ({

React.useEffect(() => {
// first render, or the preference have been cleared
const columns = React.Children.toArray(props.children)
const newAvailableColumns = React.Children.toArray(props.children)
.filter(child => React.isValidElement(child))
.map((child: React.ReactElement, index) => ({
index: String(index),
Expand All @@ -67,16 +72,82 @@ export const DatagridConfigurable = ({
child.props.label && typeof child.props.label === 'string' // this list is serializable, so we can't store ReactElement in it
? child.props.label
: child.props.source
? // force the label to be the source
undefined
: // no source or label, generate a label
translate('ra.configurable.Datagrid.unlabeled', {
column: index,
_: `Unlabeled column #%{column}`,
}),
? // force the label to be the source

Check failure on line 75 in packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
undefined

Check failure on line 76 in packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
: // no source or label, generate a label

Check failure on line 77 in packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
translate('ra.configurable.Datagrid.unlabeled', {

Check failure on line 78 in packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Replace `··························` with `····························`
column: index,

Check failure on line 79 in packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
_: `Unlabeled column #%{column}`,

Check failure on line 80 in packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Replace `······························` with `································`
}),

Check failure on line 81 in packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Insert `··`
}));
if (columns.length !== availableColumns.length) {
setAvailableColumns(columns);
const hasChanged = newAvailableColumns.some(column => {
const availableColumn = availableColumns.find(
availableColumn =>
(!!availableColumn.source &&
availableColumn.source === column?.source) ||
(!!availableColumn.label &&
availableColumn.label === column?.label)
);
return !availableColumn || availableColumn.index !== column.index;
});
if (hasChanged) {
// first we need to update the columns indexes to match the new availableColumns so we keep the same order
const newColumnsSortedAsOldColumns = columns.flatMap(column => {
const oldColumn = availableColumns.find(
availableColumn => availableColumn.index === column
);
const newColumn = newAvailableColumns.find(
availableColumn =>
(!!availableColumn.source &&
availableColumn.source === oldColumn?.source) ||
(!!availableColumn.label &&
availableColumn.label === oldColumn?.label)
);
return newColumn?.index ? [newColumn.index] : [];
});
setColumns([
// we add the old columns in the same order as before
...newColumnsSortedAsOldColumns,
// then we add at the new columns which are not omited
...newAvailableColumns
.filter(
c =>
!availableColumns.some(
ac =>
(!!ac.source && ac.source === c.source) ||
(!!ac.label && ac.label === c.label)
) && !omit?.includes(c.source as string)
)
.map(c => c.index),
]);

// Then we update the available columns to include the new columns while keeping the same order as before
const newAvailableColumnsSortedAsBefore = [
// First the existing columns, in the same order
...(availableColumns
.map(oldAvailableColumn =>
newAvailableColumns.find(
c =>
(!!c.source &&
c.source === oldAvailableColumn.source) ||
(!!c.label &&
c.label === oldAvailableColumn.label)
)
)
.filter(c => !!c) as ConfigurableDatagridColumn[]), // Remove undefined columns
// Then the new columns
...newAvailableColumns.filter(
c =>
!availableColumns.some(
oldAvailableColumn =>
(!!oldAvailableColumn.source &&
oldAvailableColumn.source === c.source) ||
(!!oldAvailableColumn.label &&
oldAvailableColumn.label === c.label)
)
),
];
setAvailableColumns(newAvailableColumnsSortedAsBefore);
setOmit(omit);
}
}, [availableColumns]); // eslint-disable-line react-hooks/exhaustive-deps
Expand Down

0 comments on commit 344746a

Please sign in to comment.