From c5713c91872f789e833e11444d3f4d301a29db22 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 17 Jan 2024 01:08:55 +0000 Subject: [PATCH] [Discover] Data Grid Pagination Options (#5610) * Added helper function to generate page options based on UI setting value. Signed-off-by: Kishor Rathva * Added dynamic pagination based on config value for data grid table Signed-off-by: Kishor Rathva * Update changelog Signed-off-by: Kishor Rathva * Removed service object from the props. Signed-off-by: kishor82 * Added suggested changes and updated tests. Signed-off-by: kishor82 * fix functional test issue due to ui setting Signed-off-by: kishor82 --------- Signed-off-by: Kishor Rathva Signed-off-by: kishor82 (cherry picked from commit e83b7ee42831d7e62b81ad906b998ff035355640) Signed-off-by: github-actions[bot] # Conflicts: # CHANGELOG.md --- .../components/data_grid/data_grid_table.tsx | 8 +++- .../utils/page_size_options.test.ts | 40 +++++++++++++++++++ .../components/utils/page_size_options.ts | 29 ++++++++++++++ .../components/utils/use_pagination.test.ts | 17 ++++---- .../components/utils/use_pagination.ts | 13 ++++-- 5 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 src/plugins/discover/public/application/components/utils/page_size_options.test.ts create mode 100644 src/plugins/discover/public/application/components/utils/page_size_options.ts diff --git a/src/plugins/discover/public/application/components/data_grid/data_grid_table.tsx b/src/plugins/discover/public/application/components/data_grid/data_grid_table.tsx index 655eb087e84..1bac2f0f406 100644 --- a/src/plugins/discover/public/application/components/data_grid/data_grid_table.tsx +++ b/src/plugins/discover/public/application/components/data_grid/data_grid_table.tsx @@ -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[]; @@ -52,9 +55,12 @@ export const DataGridTable = ({ isContextView = false, isLoading = false, }: DataGridTableProps) => { + const { services } = useOpenSearchDashboards(); + const [inspectedHit, setInspectedHit] = useState(); 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 diff --git a/src/plugins/discover/public/application/components/utils/page_size_options.test.ts b/src/plugins/discover/public/application/components/utils/page_size_options.test.ts new file mode 100644 index 00000000000..14ccc760d55 --- /dev/null +++ b/src/plugins/discover/public/application/components/utils/page_size_options.test.ts @@ -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); + }); +}); diff --git a/src/plugins/discover/public/application/components/utils/page_size_options.ts b/src/plugins/discover/public/application/components/utils/page_size_options.ts new file mode 100644 index 00000000000..93e527f129c --- /dev/null +++ b/src/plugins/discover/public/application/components/utils/page_size_options.ts @@ -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]; diff --git a/src/plugins/discover/public/application/components/utils/use_pagination.test.ts b/src/plugins/discover/public/application/components/utils/use_pagination.test.ts index 6eda1f7b4ca..0a6f7363d80 100644 --- a/src/plugins/discover/public/application/components/utils/use_pagination.test.ts +++ b/src/plugins/discover/public/application/components/utils/use_pagination.test.ts @@ -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); @@ -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); @@ -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); @@ -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], }); }); }); diff --git a/src/plugins/discover/public/application/components/utils/use_pagination.ts b/src/plugins/discover/public/application/components/utils/use_pagination.ts index 98363e57ed9..427a18990a2 100644 --- a/src/plugins/discover/public/application/components/utils/use_pagination.ts +++ b/src/plugins/discover/public/application/components/utils/use_pagination.ts @@ -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 })), [] @@ -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] ); };