[8.3] [Lens][Agg based] Fix table pagination bug for both lens and agg based (#139160) (#139393)

* [Lens][Agg based] Fix table pagination bug for both lens and agg based (#139160)

(cherry picked from commit 90f2c80379)

* resolve type issue

Co-authored-by: Joe Reuter <johannes.reuter@elastic.co>
Co-authored-by: Andrew Tate <andrew.tate@elastic.co>
This commit is contained in:
Kibana Machine 2022-08-24 15:17:20 -04:00 committed by GitHub
parent 352176cc63
commit a25f6fbc27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 81 additions and 6 deletions

View file

@ -15,9 +15,10 @@ import { FormattedColumns } from '../types';
export const createTableVisCell =
(rows: DatatableRow[], formattedColumns: FormattedColumns, autoFitRowToContent?: boolean) =>
({ rowIndex, columnId }: EuiDataGridCellValueElementProps) => {
const rowValue = rows[rowIndex][columnId];
// incoming data might change and put the current page out of bounds - check whether row actually exists
const rowValue = rows[rowIndex]?.[columnId];
const column = formattedColumns[columnId];
const content = column.formatter.convert(rowValue, 'html');
const content = column?.formatter.convert(rowValue, 'html');
const cellContent = (
<div

View file

@ -61,7 +61,8 @@ export const createGridColumns = (
const cellActions = formattedColumn.filterable
? [
({ rowIndex, columnId, Component }: EuiDataGridColumnCellActionProps) => {
const rowValue = rows[rowIndex][columnId];
// incoming data might change and put the current page out of bounds - check whether row actually exists
const rowValue = rows[rowIndex]?.[columnId];
if (rowValue == null) return null;
const cellContent = formattedColumn.formatter.convert(rowValue);
@ -96,7 +97,8 @@ export const createGridColumns = (
);
},
({ rowIndex, columnId, Component }: EuiDataGridColumnCellActionProps) => {
const rowValue = rows[rowIndex][columnId];
// incoming data might change and put the current page out of bounds - check whether row actually exists
const rowValue = rows[rowIndex]?.[columnId];
if (rowValue == null) return null;
const cellContent = formattedColumn.formatter.convert(rowValue);

View file

@ -63,7 +63,8 @@ export const createGridColumns = (
rowIndex,
columnId,
}: Pick<EuiDataGridColumnCellActionProps, 'rowIndex' | 'columnId'>) => {
const rowValue = table.rows[rowIndex][columnId];
// incoming data might change and put the current page out of bounds - check whether row actually exists
const rowValue = table.rows[rowIndex]?.[columnId];
const column = columnsReverseLookup?.[columnId];
const contentsIsDefined = rowValue != null;

View file

@ -723,7 +723,9 @@ describe('DatatableComponent', () => {
it('enables pagination', async () => {
const { data, args } = sampleArgs();
args.pageSize = 10;
data.rows = new Array(10).fill({ a: 'shoes', b: 1588024800000, c: 3 });
args.pageSize = 2;
const wrapper = mount(
<DatatableComponent
@ -755,6 +757,56 @@ describe('DatatableComponent', () => {
expect(updatedConfig?.pageSize).toBe(args.pageSize);
});
it('resets page position if rows change so page will be empty', async () => {
const { data, args } = sampleArgs();
data.rows = new Array(10).fill({ a: 'shoes', b: 1588024800000, c: 3 });
args.pageSize = 2;
const wrapper = mount(
<DatatableComponent
data={data}
args={args}
formatFactory={(x) => x as unknown as IFieldFormat}
dispatchEvent={onDispatchEvent}
getType={jest.fn()}
paletteService={chartPluginMock.createPaletteRegistry()}
uiSettings={{ get: jest.fn() } as unknown as IUiSettingsClient}
renderMode="edit"
interactive
/>
);
const newIndex = 3;
act(() => wrapper.find(EuiDataGrid).prop('pagination')?.onChangePage(newIndex));
wrapper.update();
expect(wrapper.find(EuiDataGrid).prop('pagination')?.pageIndex).toBe(newIndex);
wrapper.setProps({
data: {
...data,
rows: new Array(20).fill({ a: 'shoes', b: 1588024800000, c: 3 }),
},
});
await waitForWrapperUpdate(wrapper);
// keeps existing page if more data is added
expect(wrapper.find(EuiDataGrid).prop('pagination')?.pageIndex).toBe(newIndex);
wrapper.setProps({
data: {
...data,
rows: new Array(3).fill({ a: 'shoes', b: 1588024800000, c: 3 }),
},
});
await waitForWrapperUpdate(wrapper);
// resets to the last page if the current page becomes out of bounds
expect(wrapper.find(EuiDataGrid).prop('pagination')?.pageIndex).toBe(1);
});
it('disables pagination by default', async () => {
const { data, args } = sampleArgs();

View file

@ -99,6 +99,25 @@ export const DatatableComponent = (props: DatatableRenderProps) => {
const firstTableRef = useRef(firstLocalTable);
firstTableRef.current = firstLocalTable;
useEffect(() => {
if (!pagination?.pageIndex && !pagination?.pageSize) return;
const lastPageIndex = Math.ceil(firstLocalTable.rows.length / pagination.pageSize) - 1;
/**
* When the underlying data changes, there might be a case when actual pagination page
* doesn't exist anymore - if the number of rows has decreased.
* Set the last page as an actual.
*/
setPagination((pag) => {
if (!pag) {
return pag;
}
return {
pageIndex: pag.pageIndex > lastPageIndex ? lastPageIndex : pag.pageIndex,
pageSize: pag.pageSize,
};
});
}, [pagination?.pageIndex, pagination?.pageSize, firstLocalTable.rows.length]);
const untransposedDataRef = useRef(props.untransposedData);
untransposedDataRef.current = props.untransposedData;