From c476dc8c0beb748b14c49d3501ec47bfd2046503 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Fri, 11 Feb 2022 14:16:10 -0800 Subject: [PATCH] Update EuiDataGrid pagination props to accept 'all' - type updates and either `'all'` or `typeof 'number'` checks (note that I generally prefer 'all' but fall back to typeof number if accounting for pagination undefined at the same time) --- src/components/datagrid/data_grid.tsx | 26 +++++++-------- src/components/datagrid/data_grid_types.ts | 12 ++++--- .../utils/data_grid_pagination.test.tsx | 33 +++++++++++++++++++ .../datagrid/utils/data_grid_pagination.tsx | 12 +++++-- src/components/datagrid/utils/focus.ts | 7 ++-- .../datagrid/utils/grid_height_width.ts | 3 +- src/components/datagrid/utils/ref.ts | 2 +- src/components/datagrid/utils/row_count.ts | 12 ++++--- 8 files changed, 75 insertions(+), 32 deletions(-) diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index 88feaf92d46..09f6d5ec96a 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -353,23 +353,20 @@ export const EuiDataGrid = forwardRef( const interactiveCellId = useGeneratedHtmlId(); const ariaLabelledById = useGeneratedHtmlId(); + const ariaPage = pagination ? pagination.pageIndex + 1 : 1; + const ariaPageCount = + typeof pagination?.pageSize === 'number' + ? Math.ceil(rowCount / pagination.pageSize) + : 1; const ariaLabel = useEuiI18n( 'euiDataGrid.ariaLabel', '{label}; Page {page} of {pageCount}.', - { - label: rest['aria-label'], - page: pagination ? pagination.pageIndex + 1 : 0, - pageCount: pagination ? Math.ceil(rowCount / pagination.pageSize) : 0, - } + { label: rest['aria-label'], page: ariaPage, pageCount: ariaPageCount } ); - const ariaLabelledBy = useEuiI18n( 'euiDataGrid.ariaLabelledBy', 'Page {page} of {pageCount}.', - { - page: pagination ? pagination.pageIndex + 1 : 0, - pageCount: pagination ? Math.ceil(rowCount / pagination.pageSize) : 0, - } + { page: ariaPage, pageCount: ariaPageCount } ); // extract aria-label and/or aria-labelledby from `rest` @@ -422,11 +419,10 @@ export const EuiDataGrid = forwardRef( renderCellValue={renderCellValue} columns={columns} rowCount={ - inMemory.level === 'enhancements' - ? // if `inMemory.level === enhancements` then we can only be sure the pagination's pageSize is available in memory - pagination?.pageSize || rowCount - : // otherwise, all of the data is present and usable - rowCount + inMemory.level === 'enhancements' && // if `inMemory.level === enhancements` then we can only be sure the pagination's pageSize is available in memory + typeof pagination?.pageSize === 'number' // If pageSize is set to 'all' instead of a number, then all rows are being displayed + ? pagination?.pageSize || rowCount + : rowCount // otherwise, all of the data is present and usable } onCellRender={onCellRender} /> diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index 617388e57af..2aac9586afd 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -722,18 +722,20 @@ export interface EuiDataGridPaginationProps { */ pageIndex: number; /** - * How many rows should initially be shown per page + * How many rows should initially be shown per page. + * Pass `'all'` to display the selected "Show all" option and hide the pagination. */ - pageSize: number; + pageSize: number | 'all'; /** * An array of page sizes the user can select from. - * Leave this prop undefined or use an empty array to hide "Rows per page" select button + * Pass `'all'` as one of the options to create a "Show all" option. + * Leave this prop undefined or use an empty array to hide "Rows per page" select button. */ - pageSizeOptions?: number[]; + pageSizeOptions?: Array; /** * A callback for when the user changes the page size selection */ - onChangeItemsPerPage: (itemsPerPage: number) => void; + onChangeItemsPerPage: (itemsPerPage: number | 'all') => void; /** * A callback for when the current page index changes */ diff --git a/src/components/datagrid/utils/data_grid_pagination.test.tsx b/src/components/datagrid/utils/data_grid_pagination.test.tsx index e76be9718b1..6a312453dac 100644 --- a/src/components/datagrid/utils/data_grid_pagination.test.tsx +++ b/src/components/datagrid/utils/data_grid_pagination.test.tsx @@ -101,6 +101,39 @@ describe('EuiDataGridPaginationRenderer', () => { `); }); + it('handles the "all" page size option', () => { + const component = shallow( + + ); + expect(component).toMatchInlineSnapshot(` +
+ +
+ `); + }); + it('does not render if there are fewer rows than the smallest page size option', () => { const component = shallow( a - b)[0]; + pageSizeOptions?.length && + [...pageSizeOptions].reduce((a, b) => { + // Account for 'all' strings + if (typeof b !== 'number') return a; + if (typeof a !== 'number') return b; + // Find the smallest number + return Math.min(a, b); + }); if (rowCount < (minSizeOption || pageSize)) { /** diff --git a/src/components/datagrid/utils/focus.ts b/src/components/datagrid/utils/focus.ts index 910e067a70a..1bcfdc023d9 100644 --- a/src/components/datagrid/utils/focus.ts +++ b/src/components/datagrid/utils/focus.ts @@ -215,10 +215,9 @@ export const createKeyDownHandler = ({ setFocusedCell([x + 1, y]); } } else if (key === keys.PAGE_DOWN) { - if (pagination) { + if (pagination && pagination.pageSize !== 'all') { event.preventDefault(); - const pageSize = pagination.pageSize; - const pageCount = Math.ceil(rowCount / pageSize); + const pageCount = Math.ceil(rowCount / pagination.pageSize); const pageIndex = pagination.pageIndex; if (pageIndex < pageCount - 1) { pagination.onChangePage(pageIndex + 1); @@ -226,7 +225,7 @@ export const createKeyDownHandler = ({ setFocusedCell([focusedCell[0], 0]); } } else if (key === keys.PAGE_UP) { - if (pagination) { + if (pagination && pagination.pageSize !== 'all') { event.preventDefault(); const pageIndex = pagination.pageIndex; if (pageIndex > 0) { diff --git a/src/components/datagrid/utils/grid_height_width.ts b/src/components/datagrid/utils/grid_height_width.ts index 24aad7108bf..e4d94460a63 100644 --- a/src/components/datagrid/utils/grid_height_width.ts +++ b/src/components/datagrid/utils/grid_height_width.ts @@ -10,6 +10,7 @@ import { useEffect, useState, useContext, MutableRefObject } from 'react'; import { IS_JEST_ENVIRONMENT } from '../../../test'; import { useUpdateEffect, useForceRender } from '../../../services'; import { useResizeObserver } from '../../observer/resize_observer'; +import { EuiTablePaginationProps } from '../../table/table_pagination'; import { EuiDataGridRowHeightsOptions } from '../data_grid_types'; import { RowHeightUtils } from './row_heights'; import { DataGridSortingContext } from './sorting'; @@ -162,7 +163,7 @@ export const useUnconstrainedHeight = ({ export const useVirtualizeContainerWidth = ( virtualizeContainer: HTMLDivElement | null, gridWidth: number, - pageSize: number | undefined + pageSize: EuiTablePaginationProps['itemsPerPage'] ) => { const [virtualizeContainerWidth, setVirtualizeContainerWidth] = useState(0); useResizeObserver(virtualizeContainer); diff --git a/src/components/datagrid/utils/ref.ts b/src/components/datagrid/utils/ref.ts index 88aebb8eb8d..34f3ee0ebfa 100644 --- a/src/components/datagrid/utils/ref.ts +++ b/src/components/datagrid/utils/ref.ts @@ -135,7 +135,7 @@ export const useSortPageCheck = ( : rowIndex; // Account for pagination - if (pagination) { + if (pagination && pagination.pageSize !== 'all') { const pageIndex = Math.floor(visibleRowIndex / pagination.pageSize); // If the targeted row is on a different page than the current page, // we should automatically navigate the user to the correct page diff --git a/src/components/datagrid/utils/row_count.ts b/src/components/datagrid/utils/row_count.ts index 81bf03050b2..c32bc6062e2 100644 --- a/src/components/datagrid/utils/row_count.ts +++ b/src/components/datagrid/utils/row_count.ts @@ -15,11 +15,15 @@ export const computeVisibleRows = ({ pagination: EuiDataGridProps['pagination']; rowCount: EuiDataGridProps['rowCount']; }): EuiDataGridVisibleRows => { - const startRow = pagination ? pagination.pageIndex * pagination.pageSize : 0; + const startRow = + pagination && pagination.pageSize !== 'all' + ? pagination.pageIndex * pagination.pageSize + : 0; - let endRow = pagination - ? (pagination.pageIndex + 1) * pagination.pageSize - : rowCount; + let endRow = + pagination && pagination.pageSize !== 'all' + ? (pagination.pageIndex + 1) * pagination.pageSize + : rowCount; endRow = Math.min(endRow, rowCount); const visibleRowCount = endRow - startRow;