Fix pagination state problem in TableListView (#132930)

This commit is contained in:
Sébastien Loix 2022-05-31 17:02:25 +02:00 committed by GitHub
parent cbca99d860
commit 591aa648d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 109 additions and 21 deletions

View file

@ -132,14 +132,14 @@ exports[`TableListView render list view 1`] = `
onChange={[Function]}
pagination={
Object {
"initialPageIndex": 0,
"initialPageSize": 5,
"pageIndex": 0,
"pageSize": 20,
"pageSizeOptions": Array [
10,
20,
5,
50,
],
"totalItemCount": 1,
}
}
responsive={true}
@ -156,11 +156,6 @@ exports[`TableListView render list view 1`] = `
"toolsLeft": undefined,
}
}
sorting={
Object {
"sort": undefined,
}
}
tableCaption="test caption"
tableLayout="fixed"
/>

View file

@ -27,9 +27,9 @@ jest.mock('lodash', () => {
const requiredProps: TableListViewProps<Record<string, unknown>> = {
entityName: 'test',
entityNamePlural: 'tests',
listingLimit: 5,
listingLimit: 500,
initialFilter: '',
initialPageSize: 5,
initialPageSize: 20,
tableColumns: [],
tableListTitle: 'test title',
rowHeader: 'name',
@ -245,4 +245,80 @@ describe('TableListView', () => {
]);
});
});
describe('pagination', () => {
let testBed: TestBed;
const tableColumns = [
{
field: 'title',
name: 'Title',
sortable: true,
},
];
const initialPageSize = 20;
const totalItems = 30;
const hits = new Array(totalItems).fill(' ').map((_, i) => ({
title: `Item ${i < 10 ? `0${i}` : i}`, // prefix with "0" for correct A-Z sorting
}));
const findItems = jest.fn().mockResolvedValue({ total: hits.length, hits });
const defaultProps: TableListViewProps<Record<string, unknown>> = {
...requiredProps,
initialPageSize,
tableColumns,
findItems,
createItem: () => undefined,
};
const setup = registerTestBed(TableListView, { defaultProps });
test('should limit the number of row to the `initialPageSize` provided', async () => {
await act(async () => {
testBed = await setup();
});
const { component, table } = testBed!;
component.update();
const { tableCellsValues } = table.getMetaData('itemsInMemTable');
expect(tableCellsValues.length).toBe(requiredProps.initialPageSize);
const [[firstRowTitle]] = tableCellsValues;
const [lastRowTitle] = tableCellsValues[tableCellsValues.length - 1];
expect(firstRowTitle).toBe('Item 00');
expect(lastRowTitle).toBe('Item 19');
});
test('should navigate to page 2', async () => {
await act(async () => {
testBed = await setup();
});
const { component, table } = testBed!;
component.update();
const pageLinks = component.find('.euiPagination__list .euiPagination__item');
expect(pageLinks.length).toBe(Math.ceil(totalItems / initialPageSize));
act(() => {
// Click on page 2
pageLinks.at(1).find('a').simulate('click');
});
component.update();
const { tableCellsValues } = table.getMetaData('itemsInMemTable');
expect(tableCellsValues.length).toBe(totalItems - initialPageSize);
const [[firstRowTitle]] = tableCellsValues;
const [lastRowTitle] = tableCellsValues[tableCellsValues.length - 1];
expect(firstRowTitle).toBe('Item 20');
expect(lastRowTitle).toBe('Item 29');
});
});
});

View file

@ -13,7 +13,8 @@ import {
EuiConfirmModal,
EuiEmptyPrompt,
EuiInMemoryTable,
Criteria,
Pagination,
CriteriaWithPagination,
PropertySort,
Direction,
EuiLink,
@ -78,6 +79,7 @@ export interface TableListViewState<V> {
filter: string;
selectedIds: string[];
totalItems: number;
pagination: Pagination;
tableSort?: {
field: keyof V;
direction: Direction;
@ -93,18 +95,11 @@ class TableListView<V extends {}> extends React.Component<
TableListViewProps<V>,
TableListViewState<V>
> {
private pagination = {};
private _isMounted = false;
constructor(props: TableListViewProps<V>) {
super(props);
this.pagination = {
initialPageIndex: 0,
initialPageSize: props.initialPageSize,
pageSizeOptions: uniq([10, 20, 50, props.initialPageSize]).sort(),
};
this.state = {
items: [],
totalItems: 0,
@ -116,6 +111,12 @@ class TableListView<V extends {}> extends React.Component<
showLimitError: false,
filter: props.initialFilter,
selectedIds: [],
pagination: {
pageIndex: 0,
totalItemCount: 0,
pageSize: props.initialPageSize,
pageSizeOptions: uniq([10, 20, 50, props.initialPageSize]).sort(),
},
};
}
@ -149,6 +150,10 @@ class TableListView<V extends {}> extends React.Component<
direction: 'desc' as const,
}
: prev.tableSort,
pagination: {
...prev.pagination,
totalItemCount: this.state.items.length,
},
};
});
}
@ -454,7 +459,19 @@ class TableListView<V extends {}> extends React.Component<
);
}
onTableChange(criteria: Criteria<V>) {
onTableChange(criteria: CriteriaWithPagination<V>) {
this.setState((prev) => {
const tableSort = criteria.sort ?? prev.tableSort;
return {
pagination: {
...prev.pagination,
pageIndex: criteria.page.index,
pageSize: criteria.page.size,
},
tableSort,
};
});
if (criteria.sort) {
this.setState({ tableSort: criteria.sort });
}
@ -499,12 +516,12 @@ class TableListView<V extends {}> extends React.Component<
itemId="id"
items={this.state.items}
columns={this.getTableColumns()}
pagination={this.pagination}
pagination={this.state.pagination}
loading={this.state.isFetchingItems}
message={noItemsMessage}
selection={selection}
search={search}
sorting={{ sort: this.state.tableSort as PropertySort }}
sorting={this.state.tableSort ? { sort: this.state.tableSort as PropertySort } : undefined}
onChange={this.onTableChange.bind(this)}
data-test-subj="itemsInMemTable"
rowHeader={this.props.rowHeader}