UNPKG

@3mo/fetchable-data-grid

Version:

A fetchable variant of @3mo/data-grid

174 lines (172 loc) 6.56 kB
import { __decorate } from "tslib"; import { Binder, component, css, event, html, property, bind } from '@a11d/lit'; import { hasChanged } from '@a11d/equals'; import { Localizer } from '@3mo/localization'; import { DataGrid } from '@3mo/data-grid'; import { FetchableDataGridFetcherController } from './FetchableDataGridFetcherController.js'; import './FetchableDataGridRefetchIconButton.js'; Localizer.dictionaries.add('de', { 'Make a filter selection': 'Filterauswahl vornehmen', }); /** * @element mo-fetchable-data-grid * * @attr fetch - A function that fetches the data from the server. * @attr silentFetch - If set, the DataGrid's content will not be cleared when the fetch is initiated. * @attr parameters - The parameters that are passed to the fetch function. * @attr paginationParameters - The parameters that are passed to the fetch function when the page changes. This enables server-side pagination. * @attr sortParameters - The parameters that are passed to the fetch function when the sort changes. This enables server-side sorting. * @attr autoRefetch - The interval in seconds at which the data should be refetched automatically. If set, the DataGrid will automatically refetch the data at the specified interval. * * @slot error-no-selection - A slot for displaying an error message when user action is required in order for DataGrid to initiate the fetch. * * @fires parametersChange * @fires dataFetch */ let FetchableDataGrid = class FetchableDataGrid extends DataGrid { constructor() { super(...arguments); this.fetch = () => Promise.resolve([]); this.silentFetch = false; this.fetcherController = new FetchableDataGridFetcherController(this); this.parametersBinder = new Binder(this, 'parameters'); } get hasNextPage() { return !this.hasServerSidePagination ? super.hasNextPage : this.fetcherController.hasNextPage; } get dataLength() { return !this.hasServerSidePagination ? super.dataLength : this.fetcherController.dataLength; } requestFetch(...parameters) { return this.fetcherController.fetch(...parameters); } static get styles() { return css ` ${super.styles} mo-circular-progress { position: absolute; width: 48px; height: 48px; inset-inline-start: 50%; inset-block-start: 50%; transform: translate(-50%, calc(-50% + var(--mo-data-grid-header-height) / 2)); } `; } get hasServerSidePagination() { return this.paginationParameters !== undefined; } get hasServerSideSort() { return this.sortParameters !== undefined; } setParameters(parameters) { this.parameters = parameters; this.parametersChange.dispatch(this.parameters); } get dataSkip() { return !this.hasServerSidePagination ? super.dataSkip : 0; } get dataTake() { return !this.hasServerSidePagination ? super.dataTake : Number.MAX_SAFE_INTEGER; } async *getCsvData() { const data = new Array(); const pageSize = 500; const parameters = { ...this.parameters }; const sortParameters = this.sortParameters?.() ?? {}; let dataLength = this.dataLength; let hasNextPage = true; let page = 1; while (true) { const paginationParameters = this.paginationParameters?.({ page, pageSize }) ?? {}; const result = await this.fetch({ ...parameters, ...paginationParameters, ...sortParameters, }) ?? []; if (result instanceof Array) { data.push(...result); hasNextPage = false; dataLength = data.length; } else { dataLength = result.dataLength ?? 0; hasNextPage = result.hasNextPage ?? (page < Math.ceil(result.dataLength / pageSize)); data.push(...result.data); } page++; yield Math.min(Math.floor(data.length / dataLength * 100) / 100, 1); if (!hasNextPage) { break; } } return [...this.getFlattenedData(data)]; } get hasPagination() { return super.hasPagination || this.hasServerSidePagination; } get supportsDynamicPageSize() { return super.supportsDynamicPageSize && !this.hasServerSidePagination; } get toolbarActionsTemplate() { return html ` <mo-fetchable-data-grid-refetch-icon-button ?fetching=${this.fetcherController.pending} autoRefetch=${bind(this, 'autoRefetch')} @requestFetch=${() => this.requestFetch()} ></mo-fetchable-data-grid-refetch-icon-button> ${super.toolbarActionsTemplate} `; } get contentTemplate() { this.toggleAttribute('fetching', this.fetcherController.pending); switch (true) { case this.fetcherController.pending && this.fetcherController.silent === false: return this.fetchingTemplate; case this.data.length === 0 && this.parameters === undefined: return this.noSelectionTemplate; default: return super.contentTemplate; } } get fetchingTemplate() { return html ` <mo-circular-progress></mo-circular-progress> `; } get noSelectionTemplate() { return html ` <slot name='error-no-selection'> <mo-empty-state icon='touch_app'>${t('Make a filter selection')}</mo-empty-state> </slot> `; } }; __decorate([ event() ], FetchableDataGrid.prototype, "parametersChange", void 0); __decorate([ event() ], FetchableDataGrid.prototype, "dataFetch", void 0); __decorate([ property({ type: Object, hasChanged }) ], FetchableDataGrid.prototype, "fetch", void 0); __decorate([ property({ type: Boolean }) ], FetchableDataGrid.prototype, "silentFetch", void 0); __decorate([ property({ type: Object, hasChanged }) ], FetchableDataGrid.prototype, "parameters", void 0); __decorate([ property({ type: Object, hasChanged }) ], FetchableDataGrid.prototype, "paginationParameters", void 0); __decorate([ property({ type: Object, hasChanged }) ], FetchableDataGrid.prototype, "sortParameters", void 0); __decorate([ property({ type: Number, updated() { this.fetcherController.updateTimer(); } }) ], FetchableDataGrid.prototype, "autoRefetch", void 0); FetchableDataGrid = __decorate([ component('mo-fetchable-data-grid') ], FetchableDataGrid); export { FetchableDataGrid };