From 7ffa41e4a6b29bf6ea6fd0b4ea7381c5f770b088 Mon Sep 17 00:00:00 2001 From: Ovidijus Parsiunas Date: Mon, 19 Feb 2024 20:22:16 +0000 Subject: [PATCH] updating the pagination API --- .../numberOfVisibleRowsElement.ts | 3 +- component/src/elements/table/tableElement.ts | 2 + component/src/types/paginationInternal.ts | 2 +- .../src/utils/data/initialDataProcessing.ts | 2 +- .../async/paginationAsyncStartData.ts | 55 +++++++++++++++++++ .../pagination/async/paginationAsyncUtils.ts | 20 +------ .../pagination/paginationInternalUtils.ts | 12 +++- 7 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 component/src/utils/outerTableComponents/pagination/async/paginationAsyncStartData.ts diff --git a/component/src/elements/pagination/numberOfVisibleRows/numberOfVisibleRowsElement.ts b/component/src/elements/pagination/numberOfVisibleRows/numberOfVisibleRowsElement.ts index 3a52e4c3..ccefcf18 100644 --- a/component/src/elements/pagination/numberOfVisibleRows/numberOfVisibleRowsElement.ts +++ b/component/src/elements/pagination/numberOfVisibleRows/numberOfVisibleRowsElement.ts @@ -24,7 +24,8 @@ export class NumberOfVisibleRowsElement { const {numberOfVisibleRowsElement, isAllRowsOptionSelected} = _pagination; if (!numberOfVisibleRowsElement) return; // using max as when there is no data on startup - dataRowsLength is -1 - const dataRowsLength = Math.max(dataStartsAtHeader ? data.length : data.length - 1, 0); + const dataRowsLength = + at._pagination?.asyncStartData?.totalDataRows || Math.max(dataStartsAtHeader ? data.length : data.length - 1, 0); if (isAllRowsOptionSelected) { NumberOfVisibleRowsElement.updateForAllRows(numberOfVisibleRowsElement, dataRowsLength); } else { diff --git a/component/src/elements/table/tableElement.ts b/component/src/elements/table/tableElement.ts index 5122efbf..3b27e0d0 100644 --- a/component/src/elements/table/tableElement.ts +++ b/component/src/elements/table/tableElement.ts @@ -1,3 +1,4 @@ +import {PaginationAsyncStartData} from '../../utils/outerTableComponents/pagination/async/paginationAsyncStartData'; import {StaticTableWidthUtils} from '../../utils/tableDimensions/staticTable/staticTableWidthUtils'; import {MaximumColumns} from '../../utils/insertRemoveStructure/insert/maximum/maximumColumns'; import {FrameComponentsElements} from '../../utils/frameComponents/frameComponentsElements'; @@ -64,6 +65,7 @@ export class TableElement { if (!MaximumColumns.canAddMore(at)) return; StaticTableWidthUtils.toggleWidthUsingMaxWidth(at, true); at.data.map((row: TableRow, rowIndex: number) => InsertNewRow.insert(at, rowIndex, false, row)); + if (at._pagination.asyncStartData) PaginationAsyncStartData.populate(at, at._pagination.asyncStartData); StaticTableWidthUtils.toggleWidthUsingMaxWidth(at, false); } diff --git a/component/src/types/paginationInternal.ts b/component/src/types/paginationInternal.ts index b693afde..3b944625 100644 --- a/component/src/types/paginationInternal.ts +++ b/component/src/types/paginationInternal.ts @@ -14,7 +14,7 @@ export interface IPaginationStyles extends PaginationStyles { return Math.max(currentMax, row.length); }, 0); diff --git a/component/src/utils/outerTableComponents/pagination/async/paginationAsyncStartData.ts b/component/src/utils/outerTableComponents/pagination/async/paginationAsyncStartData.ts new file mode 100644 index 00000000..5d9ca449 --- /dev/null +++ b/component/src/utils/outerTableComponents/pagination/async/paginationAsyncStartData.ts @@ -0,0 +1,55 @@ +import {PageButtonContainerElement} from '../../../../elements/pagination/pageButtons/pageButtonContainerElement'; +import {UpdateCellsForRows} from '../../../insertRemoveStructure/update/updateCellsForRows'; +import {AsyncStartData, PaginationInternal} from '../../../../types/paginationInternal'; +import {InsertNewRow} from '../../../insertRemoveStructure/insert/insertNewRow'; +import {InitialDataProcessing} from '../../../data/initialDataProcessing'; +import {CELL_UPDATE_TYPE} from '../../../../enums/onUpdateCellType'; +import {PaginationAsyncUtils} from './paginationAsyncUtils'; +import {Pagination} from '../../../../types/pagination'; +import {EMPTY_STRING} from '../../../../consts/text'; +import {ActiveTable} from '../../../../activeTable'; + +export class PaginationAsyncStartData { + private static fillTotalDataRows(at: ActiveTable, asyncStartData: AsyncStartData) { + const {totalDataRows, data: asyncData, failed} = asyncStartData; + if (at.data.length < totalDataRows || failed) { + const maxRowLength = Math.max(at.data[0]?.length || 0, InitialDataProcessing.getMaxRowLength(asyncData)); + const headerDelta = Number(!at.dataStartsAtHeader); + const newData = new Array(totalDataRows - at.data.length + headerDelta).fill( + new Array(maxRowLength).fill(EMPTY_STRING) + ); + const startIndex = at.data.length; + at.data.splice(at.data.length, 0, ...newData); + newData.forEach((row, index) => { + const rowEl = InsertNewRow.insertNewRow(at, startIndex + index, false, row); + setTimeout(() => { + UpdateCellsForRows.updateRowCells(at, rowEl, startIndex + index, CELL_UPDATE_TYPE.UPDATE, false); + }); + }); + PageButtonContainerElement.repopulateButtons(at); + } + } + + public static populate(at: ActiveTable, startData: AsyncStartData) { + const {data, totalDataRows, failed} = startData; + if (data.length > 0 && totalDataRows > 0 && (at.data.length > 0 || InitialDataProcessing.getMaxRowLength(data) > 0)) { + PaginationAsyncStartData.fillTotalDataRows(at, startData); + if (!failed) PaginationAsyncUtils.insertData(at, data, 1); + } + } + + public static async get(at: ActiveTable, pagination: Pagination, paginationInternal: PaginationInternal) { + const {_async, rowsPerPage: rowsPerPageC} = pagination; + if (!_async) return; + const {rowsPerPage: rowsPerPageI} = paginationInternal; + const rowsPerPage = typeof rowsPerPageC === 'number' ? rowsPerPageC : rowsPerPageI; + try { + // not handling partial failures because users would be looking at partial data without knowing about it + const [totalDataRows, data] = await Promise.all([_async.getTotalRows(), _async.getPageData(1, rowsPerPage)]); + return {totalDataRows, data}; + } catch (e) { + setTimeout(() => PaginationAsyncUtils.displayError(e, at)); + return {totalDataRows: 0, data: [['', '']], failed: true}; + } + } +} diff --git a/component/src/utils/outerTableComponents/pagination/async/paginationAsyncUtils.ts b/component/src/utils/outerTableComponents/pagination/async/paginationAsyncUtils.ts index 0eb0d323..671574fa 100644 --- a/component/src/utils/outerTableComponents/pagination/async/paginationAsyncUtils.ts +++ b/component/src/utils/outerTableComponents/pagination/async/paginationAsyncUtils.ts @@ -1,16 +1,15 @@ import {UpdateIndexColumnWidth} from '../../../../elements/indexColumn/updateIndexColumnWidth'; -import {Pagination, PaginationAsync} from '../../../../types/pagination'; -import {PaginationInternal} from '../../../../types/paginationInternal'; import {ColumnTypesUtils} from '../../../columnType/columnTypesUtils'; import {CellEvents} from '../../../../elements/cell/cellEvents'; import {CellText, TableData} from '../../../../types/tableData'; +import {PaginationAsync} from '../../../../types/pagination'; import {LoadingElement} from '../../loading/loadingElement'; import {ErrorElement} from '../../error/errorElement'; import {ActiveTable} from '../../../../activeTable'; import {PaginationUtils} from '../paginationUtils'; export class PaginationAsyncUtils { - private static displayError(e: unknown, at: ActiveTable) { + public static displayError(e: unknown, at: ActiveTable) { ErrorElement.display(at); console.error(e); console.error('Error fetching page information'); @@ -60,19 +59,4 @@ export class PaginationAsyncUtils { at._activeOverlayElements.loading?.remove(); PaginationUtils.displayRowsForDifferentButton(at, buttonNumber); } - - public static async getStartDetails(at: ActiveTable, pagination: Pagination, paginationInternal: PaginationInternal) { - const {_async, rowsPerPage: rowsPerPageC} = pagination; - if (!_async) return; - const {rowsPerPage: rowsPerPageI} = paginationInternal; - const rowsPerPage = typeof rowsPerPageC === 'number' ? rowsPerPageC : rowsPerPageI; - try { - // not handling partial failures because users would be looking at partial data without knowing about it - const [totalRows, data] = await Promise.all([_async.getTotalRows(), _async.getPageData(1, rowsPerPage)]); - return {totalRows, data}; - } catch (e) { - setTimeout(() => PaginationAsyncUtils.displayError(e, at)); - return {totalRows: 0, data: [['', '']], failed: true}; - } - } } diff --git a/component/src/utils/outerTableComponents/pagination/paginationInternalUtils.ts b/component/src/utils/outerTableComponents/pagination/paginationInternalUtils.ts index 618ffc82..127fe21d 100644 --- a/component/src/utils/outerTableComponents/pagination/paginationInternalUtils.ts +++ b/component/src/utils/outerTableComponents/pagination/paginationInternalUtils.ts @@ -2,9 +2,12 @@ import {RowsPerPageDropdownItem} from '../../../elements/pagination/rowsPerPageS import {RowsPerPageSelect, PaginationPositions, PageButtonStyles, Pagination} from '../../../types/pagination'; import {PageButtonElement} from '../../../elements/pagination/pageButtons/pageButtonElement'; import {IPaginationStyles, PaginationInternal} from '../../../types/paginationInternal'; +import {PaginationAsyncStartData} from './async/paginationAsyncStartData'; import {FilterInternalUtils} from '../filter/rows/filterInternalUtils'; import {OuterContentPosition} from '../../../types/outerContainer'; +import {LoadingElement} from '../loading/loadingElement'; import {StatefulCSS} from '../../../types/cssStyle'; +import {ErrorElement} from '../error/errorElement'; import {ActiveTable} from '../../../activeTable'; interface DefaultBackgroundColors { @@ -222,10 +225,15 @@ export class PaginationInternalUtils { delete pagination.positions; // deleted so that Object.assign wouldn't apply it } - public static process(at: ActiveTable) { - const {_pagination} = at; + public static async process(at: ActiveTable) { + const {_pagination, _activeOverlayElements} = at; if (!at.pagination) return; const pagination: Pagination = typeof at.pagination === 'boolean' ? {} : at.pagination; + if (pagination._async) { + LoadingElement.addInitial(at); + _activeOverlayElements.error = ErrorElement.create(); + _pagination.asyncStartData = await PaginationAsyncStartData.get(at, pagination, _pagination); + } if (pagination.maxNumberOfVisiblePageButtons !== undefined && pagination.maxNumberOfVisiblePageButtons < 1) { pagination.maxNumberOfVisiblePageButtons = 1; }