Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] Enable Table Pagination #118557

Merged
merged 34 commits into from
Nov 22, 2021
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f4fe841
Add setting which allow user to fit row to content
VladLasitsa Oct 25, 2021
88efd7d
Fix lint
VladLasitsa Oct 25, 2021
4a0ae66
Merge branch 'main' into 115582
kibanamachine Nov 1, 2021
f8512ee
Change icon
VladLasitsa Nov 1, 2021
895d97c
Merge branch 'main' into 115582
kibanamachine Nov 2, 2021
b246b8e
Fix switch behavior
VladLasitsa Nov 2, 2021
59f3677
Merge branch 'main' into 115582
kibanamachine Nov 4, 2021
72bbe4b
Merge branch 'main' into 115582
kibanamachine Nov 8, 2021
c34e3d3
Fix some nits
VladLasitsa Nov 11, 2021
a6102e4
Merge branch 'main' into 115582
kibanamachine Nov 11, 2021
d40b139
Fix comments
VladLasitsa Nov 11, 2021
d1fe075
Fix lint
VladLasitsa Nov 11, 2021
75b7d00
Fix lint
VladLasitsa Nov 11, 2021
1295c27
Merge branch '115582' of https://github.com/VladLasitsa/kibana into 9…
drewdaemon Nov 11, 2021
3ff69a7
add pagination support to datatable
drewdaemon Nov 11, 2021
9b29c9c
make datatable dynamically respond to pagination settings
drewdaemon Nov 11, 2021
cd8af03
wire pagination toggling up to the toolbar
drewdaemon Nov 11, 2021
fee8ad2
Merge branch 'main' of github.com:elastic/kibana into 96778/table-pag…
drewdaemon Nov 15, 2021
4a59d78
change numerical page size to boolean toggle
drewdaemon Nov 15, 2021
5474dfa
translate string
drewdaemon Nov 15, 2021
f475c1e
Add datatable toolbar test
drewdaemon Nov 15, 2021
163723c
test datatable toExpression
drewdaemon Nov 15, 2021
fa1ee1c
Merge branch 'main' into 96778/table-pagination
kibanamachine Nov 15, 2021
750c770
enable state to preserve default page size during paging toggle
drewdaemon Nov 17, 2021
e20cc21
persist page size in visualization state
drewdaemon Nov 17, 2021
5a86c55
Merge branch 'main' into 96778/table-pagination
kibanamachine Nov 18, 2021
7b1c75a
Merge branch 'main' into 96778/table-pagination
drewdaemon Nov 18, 2021
86ef429
Merge branch '96778/table-pagination' of github.com:andrewctate/kiban…
drewdaemon Nov 18, 2021
09a9e18
Add pagination warning tooltip
drewdaemon Nov 18, 2021
51a72d8
eui table rendering bug workaround
drewdaemon Nov 19, 2021
32bcb73
dont apply key unless pagination is on
drewdaemon Nov 19, 2021
0a71b0c
include issue link
drewdaemon Nov 19, 2021
d97c17e
Merge branch 'main' into 96778/table-pagination
kibanamachine Nov 19, 2021
8bffe28
Merge branch 'main' into 96778/table-pagination
kibanamachine Nov 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions x-pack/plugins/lens/common/expressions/datatable/datatable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ export interface SortingState {
direction: 'asc' | 'desc' | 'none';
}

export interface PagingState {
size: number;
enabled: boolean;
}

export interface DatatableArgs {
title: string;
description?: string;
columns: ColumnConfigArg[];
sortingColumnId: SortingState['columnId'];
sortingDirection: SortingState['direction'];
fitRowToContent?: boolean;
pageSize?: PagingState['size'];
}

export const getDatatable = (
Expand Down Expand Up @@ -62,6 +68,10 @@ export const getDatatable = (
types: ['boolean'],
help: '',
},
pageSize: {
types: ['number'],
help: '',
},
},
async fn(...args) {
/** Build optimization: prevent adding extra code into initial bundle **/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
export const LENS_EDIT_SORT_ACTION = 'sort';
export const LENS_EDIT_RESIZE_ACTION = 'resize';
export const LENS_TOGGLE_ACTION = 'toggle';
export const LENS_EDIT_PAGESIZE_ACTION = 'pagesize';
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
*/

import React from 'react';
import { ReactWrapper, shallow } from 'enzyme';
import { ReactWrapper, shallow, mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { mountWithIntl } from '@kbn/test/jest';
import { EuiDataGrid } from '@elastic/eui';
import { IAggType } from 'src/plugins/data/public';
import { IFieldFormat } from 'src/plugins/field_formats/common';
import {
FieldFormatParams,
IFieldFormat,
SerializedFieldFormat,
} from 'src/plugins/field_formats/common';
import { VisualizationContainer } from '../../visualization_container';
import { EmptyPlaceholder } from '../../shared_components';
import { LensIconChartDatatable } from '../../assets/chart_datatable';
Expand All @@ -20,6 +24,9 @@ import { LensMultiTable } from '../../../common';
import { DatatableProps } from '../../../common/expressions';
import { chartPluginMock } from 'src/plugins/charts/public/mocks';
import { IUiSettingsClient } from 'kibana/public';
import { RenderMode } from 'src/plugins/expressions';

import { LENS_EDIT_PAGESIZE_ACTION } from './constants';

function sampleArgs() {
const indexPatternId = 'indexPatternId';
Expand Down Expand Up @@ -82,7 +89,7 @@ function sampleArgs() {
return { data, args };
}

function copyData(data: LensMultiTable): LensMultiTable {
function copyData<T>(data: T): T {
return JSON.parse(JSON.stringify(data));
}

Expand Down Expand Up @@ -658,4 +665,133 @@ describe('DatatableComponent', () => {

expect(wrapper.find('[data-test-subj="lnsDataTable-footer-c"]').exists()).toBe(false);
});

describe('pagination', () => {
it('enables pagination', async () => {
const { data, args } = sampleArgs();

args.pageSize = 10;

const wrapper = mount(
<DatatableComponent
data={data}
args={args}
formatFactory={(x) => x as IFieldFormat}
dispatchEvent={onDispatchEvent}
getType={jest.fn()}
paletteService={chartPluginMock.createPaletteRegistry()}
uiSettings={{ get: jest.fn() } as unknown as IUiSettingsClient}
renderMode="edit"
/>
);

const paginationConfig = wrapper.find(EuiDataGrid).prop('pagination');
expect(paginationConfig).toBeTruthy();
expect(paginationConfig?.pageIndex).toBe(0); // should start at 0
expect(paginationConfig?.pageSize).toBe(args.pageSize);

// trigger new page
const newIndex = 3;
act(() => paginationConfig?.onChangePage(newIndex));
wrapper.update();

const updatedConfig = wrapper.find(EuiDataGrid).prop('pagination');
expect(updatedConfig).toBeTruthy();
expect(updatedConfig?.pageIndex).toBe(newIndex);
expect(updatedConfig?.pageSize).toBe(args.pageSize);
});

it('disables pagination by default', async () => {
const { data, args } = sampleArgs();

delete args.pageSize;

const wrapper = mount(
<DatatableComponent
data={data}
args={args}
formatFactory={(x) => x as IFieldFormat}
dispatchEvent={onDispatchEvent}
getType={jest.fn()}
paletteService={chartPluginMock.createPaletteRegistry()}
uiSettings={{ get: jest.fn() } as unknown as IUiSettingsClient}
renderMode="edit"
/>
);

const paginationConfig = wrapper.find(EuiDataGrid).prop('pagination');
expect(paginationConfig).not.toBeTruthy();
});

it('dynamically toggles pagination', async () => {
const { data, args } = sampleArgs();

const argsWithPagination = copyData(args);
argsWithPagination.pageSize = 20;

const argsWithoutPagination = copyData(args);
delete argsWithoutPagination.pageSize;

const defaultProps = {
data,
formatFactory: (x?: SerializedFieldFormat<FieldFormatParams>) => x as IFieldFormat,
dispatchEvent: onDispatchEvent,
getType: jest.fn(),
paletteService: chartPluginMock.createPaletteRegistry(),
uiSettings: { get: jest.fn() } as unknown as IUiSettingsClient,
renderMode: 'edit' as RenderMode,
};

const wrapper = mount(
<DatatableComponent {...{ ...defaultProps, args: argsWithoutPagination }} />
);
wrapper.update();

expect(wrapper.find(EuiDataGrid).prop('pagination')).not.toBeTruthy();

wrapper.setProps({ args: argsWithPagination });
wrapper.update();

expect(wrapper.find(EuiDataGrid).prop('pagination')).toBeTruthy();

wrapper.setProps({ args: argsWithoutPagination });
wrapper.update();

expect(wrapper.find(EuiDataGrid).prop('pagination')).not.toBeTruthy();
});

it('dispatches event when page size changed', async () => {
const { data, args } = sampleArgs();

args.pageSize = 10;

const wrapper = mount(
<DatatableComponent
data={data}
args={args}
formatFactory={(x) => x as IFieldFormat}
dispatchEvent={onDispatchEvent}
getType={jest.fn()}
paletteService={chartPluginMock.createPaletteRegistry()}
uiSettings={{ get: jest.fn() } as unknown as IUiSettingsClient}
renderMode="edit"
/>
);

const paginationConfig = wrapper.find(EuiDataGrid).prop('pagination');
expect(paginationConfig).toBeTruthy();

const sizeToChangeTo = 100;
paginationConfig?.onChangeItemsPerPage(sizeToChangeTo);

expect(onDispatchEvent).toHaveBeenCalledTimes(1);
expect(onDispatchEvent).toHaveBeenCalledWith({
name: 'edit',
data: {
action: LENS_EDIT_PAGESIZE_ACTION,
size: sizeToChangeTo,
},
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import './table_basic.scss';

import React, { useCallback, useMemo, useRef, useState, useContext } from 'react';
import React, { useCallback, useMemo, useRef, useState, useContext, useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import useDeepCompareEffect from 'react-use/lib/useDeepCompareEffect';
import {
Expand All @@ -30,6 +30,7 @@ import type {
LensSortAction,
LensResizeAction,
LensToggleAction,
LensPagesizeAction,
} from './types';
import { createGridColumns } from './columns';
import { createGridCell } from './cell_value';
Expand All @@ -50,6 +51,9 @@ const gridStyle: EuiDataGridStyle = {
header: 'underline',
};

export const DEFAULT_PAGE_SIZE = 10;
const PAGE_SIZE_OPTIONS = [DEFAULT_PAGE_SIZE, 20, 30, 50, 100];

export const DatatableComponent = (props: DatatableRenderProps) => {
const [firstTable] = Object.values(props.data.tables);

Expand All @@ -60,6 +64,22 @@ export const DatatableComponent = (props: DatatableRenderProps) => {
});
const [firstLocalTable, updateTable] = useState(firstTable);

// ** Pagination config
const [pagination, setPagination] = useState<{ pageIndex: number; pageSize: number } | undefined>(
undefined
);

useEffect(() => {
setPagination(
props.args.pageSize
? {
pageIndex: 0,
pageSize: props.args.pageSize ?? DEFAULT_PAGE_SIZE,
}
: undefined
);
}, [props.args.pageSize]);

useDeepCompareEffect(() => {
setColumnConfig({
columns: props.args.columns,
Expand Down Expand Up @@ -102,11 +122,35 @@ export const DatatableComponent = (props: DatatableRenderProps) => {
);

const onEditAction = useCallback(
(data: LensSortAction['data'] | LensResizeAction['data'] | LensToggleAction['data']) => {
(
data:
| LensSortAction['data']
| LensResizeAction['data']
| LensToggleAction['data']
| LensPagesizeAction['data']
) => {
dispatchEvent({ name: 'edit', data });
},
[dispatchEvent]
);

const onChangeItemsPerPage = useCallback(
(pageSize) => onEditAction({ action: 'pagesize', size: pageSize }),
[onEditAction]
);

// active page isn't persisted, so we manage this state locally
const onChangePage = useCallback(
flash1293 marked this conversation as resolved.
Show resolved Hide resolved
(pageIndex) => {
setPagination((_pagination) => {
if (_pagination) {
return { pageSize: _pagination?.pageSize, pageIndex };
}
});
},
[setPagination]
);

const onRowContextMenuClick = useCallback(
(data: LensTableRowContextMenuEvent['data']) => {
dispatchEvent({ name: 'tableRowContextMenuClick', data });
Expand Down Expand Up @@ -346,6 +390,10 @@ export const DatatableComponent = (props: DatatableRenderProps) => {
}}
>
<EuiDataGrid
key={
// we control the key when pagination is on to circumvent an EUI rendering bug
pagination && columns.map(({ id }) => id).join('-') + '-' + pagination.pageSize
}
drewdaemon marked this conversation as resolved.
Show resolved Hide resolved
aria-label={dataGridAriaLabel}
data-test-subj="lnsDataTable"
rowHeightsOptions={
Expand All @@ -362,6 +410,14 @@ export const DatatableComponent = (props: DatatableRenderProps) => {
renderCellValue={renderCellValue}
gridStyle={gridStyle}
sorting={sorting}
pagination={
pagination && {
...pagination,
pageSizeOptions: PAGE_SIZE_OPTIONS,
onChangeItemsPerPage,
onChangePage,
}
}
onColumnResize={onColumnResize}
toolbarVisibility={false}
renderFooterCellValue={renderSummaryRow}
Expand Down
Loading