Skip to content

Commit

Permalink
[Discover] Data Grid Pagination Options (#5610) (#5701)
Browse files Browse the repository at this point in the history
* Added  helper function to generate page options based on UI setting value.

Signed-off-by: Kishor Rathva <kishorrathva8298@gmail.com>

* Added dynamic pagination based on config value for data grid table

Signed-off-by: Kishor Rathva <kishorrathva8298@gmail.com>

* Update changelog

Signed-off-by: Kishor Rathva <kishorrathva8298@gmail.com>

* Removed service object from the props.

Signed-off-by: kishor82 <kishorrathva8298@gmail.com>

* Added suggested changes and updated tests.

Signed-off-by: kishor82 <kishorrathva8298@gmail.com>

* fix functional test issue due to ui setting

Signed-off-by: kishor82 <kishorrathva8298@gmail.com>

---------

Signed-off-by: Kishor Rathva <kishorrathva8298@gmail.com>
Signed-off-by: kishor82 <kishorrathva8298@gmail.com>
(cherry picked from commit e83b7ee)
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

# Conflicts:
#	CHANGELOG.md

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
1 parent e03b034 commit c051a4d
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { DocViewFilterFn, OpenSearchSearchHit } from '../../doc_views/doc_views_
import { usePagination } from '../utils/use_pagination';
import { SortOrder } from '../../../saved_searches/types';
import { buildColumns } from '../../utils/columns';
import { useOpenSearchDashboards } from '../../../../../opensearch_dashboards_react/public';
import { DiscoverServices } from '../../../build_services';
import { SAMPLE_SIZE_SETTING } from '../../../../common';

export interface DataGridTableProps {
columns: string[];
Expand Down Expand Up @@ -52,9 +55,12 @@ export const DataGridTable = ({
isContextView = false,
isLoading = false,
}: DataGridTableProps) => {
const { services } = useOpenSearchDashboards<DiscoverServices>();

const [inspectedHit, setInspectedHit] = useState<OpenSearchSearchHit | undefined>();
const rowCount = useMemo(() => (rows ? rows.length : 0), [rows]);
const pagination = usePagination(rowCount);
const pageSizeLimit = services.uiSettings?.get(SAMPLE_SIZE_SETTING);
const pagination = usePagination({ rowCount, pageSizeLimit });

let adjustedColumns = buildColumns(columns);
// handle case where the user removes selected filed and leaves only time column
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { defaultPageOptions, generatePageSizeOptions } from './page_size_options';

describe('generatePageSizeOptions', () => {
it('generates default options and additional options based on sample size', () => {
const sampleSize = 1000;

const pageSizeOptions = generatePageSizeOptions(sampleSize);

// Expected result based on the provided sample size
const expectedOptions = [...defaultPageOptions, 500, 1000];

// Check if the generated options match the expected result
expect(pageSizeOptions).toEqual(expectedOptions);
});

it('handles edge case when sample size is less than maxSize', () => {
const sampleSize = 50;

// Call the function
const pageSizeOptions = generatePageSizeOptions(sampleSize);

// Check if the generated options match the expected result
expect(pageSizeOptions).toEqual(defaultPageOptions);
});

it('handles edge case when sample size is less than 0', () => {
const sampleSize = -10;

// Call the function
const pageSizeOptions = generatePageSizeOptions(sampleSize);

// Check if the generated options match the expected result
expect(pageSizeOptions).toEqual(defaultPageOptions);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

/**
* Generates an array of pagination options based on the provided `pageSizeLimit`.
* The array includes default values (25, 50, 100) and additional options derived from the `pageSizeLimit` setting.
* Ensures uniqueness and sorts the array in ascending order, representing available page size options for pagination.
* @param {number} pageSizeLimit - The sample size used to determine additional pagination options.
* @returns {number[]} - An array of available page size options.
*/

export const generatePageSizeOptions = (pageSizeLimit: number): number[] => {
const isInDefaultRange = pageSizeLimit < defaultPageOptions[defaultPageOptions.length - 1];

if (pageSizeLimit && pageSizeLimit > 0 && !isInDefaultRange) {
const stepSize = 500;
const pageSizeFromSetting = [...Array(Math.ceil(pageSizeLimit / stepSize)).keys()].map(
(i) => (i + 1) * stepSize
);
return Array.from(new Set([...defaultPageOptions, ...pageSizeFromSetting])).sort(
(a, b) => a - b
);
}
return defaultPageOptions;
};

export const defaultPageOptions = [25, 50, 100];
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@ import { renderHook, act } from '@testing-library/react-hooks';
import { usePagination } from './use_pagination';

describe('usePagination', () => {
const pageSizeLimit = 500;
it('should initialize correctly with visParams and nRow', () => {
const nRow = 30;
const { result } = renderHook(() => usePagination(nRow));
const { result } = renderHook(() => usePagination({ rowCount: nRow, pageSizeLimit }));

expect(result.current).toEqual({
pageIndex: 0,
pageSize: 100,
onChangeItemsPerPage: expect.any(Function),
onChangePage: expect.any(Function),
pageSizeOptions: [25, 50, 100],
pageSizeOptions: [25, 50, 100, 500],
});
});

it('should update pageSize correctly when calling onChangeItemsPerPage', () => {
const nRow = 30;
const { result } = renderHook(() => usePagination(nRow));
const { result } = renderHook(() => usePagination({ rowCount: nRow, pageSizeLimit }));

act(() => {
result.current?.onChangeItemsPerPage(20);
Expand All @@ -33,13 +34,13 @@ describe('usePagination', () => {
pageSize: 20,
onChangeItemsPerPage: expect.any(Function),
onChangePage: expect.any(Function),
pageSizeOptions: [25, 50, 100],
pageSizeOptions: [25, 50, 100, 500],
});
});

it('should update pageIndex correctly when calling onChangePage', () => {
const nRow = 30;
const { result } = renderHook(() => usePagination(nRow));
const { result } = renderHook(() => usePagination({ rowCount: nRow, pageSizeLimit }));

act(() => {
result.current?.onChangePage(1);
Expand All @@ -50,13 +51,13 @@ describe('usePagination', () => {
pageSize: 100,
onChangeItemsPerPage: expect.any(Function),
onChangePage: expect.any(Function),
pageSizeOptions: [25, 50, 100],
pageSizeOptions: [25, 50, 100, 500],
});
});

it('should correct pageIndex if it exceeds maximum page index after nRow or perPage change', () => {
const nRow = 300;
const { result } = renderHook(() => usePagination(nRow));
const { result } = renderHook(() => usePagination({ rowCount: nRow, pageSizeLimit }));

act(() => {
result.current?.onChangePage(4);
Expand All @@ -67,7 +68,7 @@ describe('usePagination', () => {
pageSize: 100,
onChangeItemsPerPage: expect.any(Function),
onChangePage: expect.any(Function),
pageSizeOptions: [25, 50, 100],
pageSizeOptions: [25, 50, 100, 500],
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
*/

import { useState, useMemo, useCallback } from 'react';
import { generatePageSizeOptions } from './page_size_options';
export interface Props {
pageSizeLimit: number;
rowCount: number;
}

export const usePagination = (rowCount: number) => {
export const usePagination = ({ rowCount, pageSizeLimit }: Props) => {
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 100 });
const pageCount = useMemo(() => Math.ceil(rowCount / pagination.pageSize), [
rowCount,
pagination,
]);

const pageSizeOptions = generatePageSizeOptions(pageSizeLimit);

const onChangeItemsPerPage = useCallback(
(pageSize: number) => setPagination((p) => ({ ...p, pageSize })),
[]
Expand All @@ -31,9 +38,9 @@ export const usePagination = (rowCount: number) => {
onChangePage,
pageIndex: pagination.pageIndex > pageCount - 1 ? 0 : pagination.pageIndex,
pageSize: pagination.pageSize,
pageSizeOptions: [25, 50, 100], // TODO: make this configurable
pageSizeOptions,
}
: undefined,
[pagination, onChangeItemsPerPage, onChangePage, pageCount]
[pagination, onChangeItemsPerPage, onChangePage, pageCount, pageSizeOptions]
);
};

0 comments on commit c051a4d

Please sign in to comment.