@rxap/data-source
Version:
Provides a set of classes and decorators for creating and managing data sources in Angular applications, including base classes, static data sources, observable data sources, and method data sources. It also includes a component for displaying data source
469 lines (459 loc) • 20.6 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, isDevMode, Injectable, Optional, Inject, Pipe } from '@angular/core';
import * as i1$1 from '@rxap/data-source';
import { RXAP_DATA_SOURCE_METADATA, RxapDataSourceError } from '@rxap/data-source';
import { AbstractPaginationDataSource, RxapAbstractPaginationDataSource } from '@rxap/data-source/pagination';
import { ToggleSubject } from '@rxap/rxjs';
import { hasIndexSignature, clone, equals } from '@rxap/utilities';
import * as i1 from 'rxjs';
import { BehaviorSubject, combineLatest, of } from 'rxjs';
import { startWith, tap, debounceTime, map, distinctUntilChanged, switchMap, retry } from 'rxjs/operators';
const RXAP_TABLE_DATA_SOURCE_PAGINATOR = new InjectionToken('rxap/data-source/table/paginator');
const RXAP_TABLE_DATA_SOURCE_SORT = new InjectionToken('rxap/data-source/table/sort');
const RXAP_TABLE_DATA_SOURCE_FILTER = new InjectionToken('rxap/data-source/table/filter');
const RXAP_TABLE_DATA_SOURCE_PARAMETERS = new InjectionToken('rxap/data-source/table/parameters');
const RXAP_TABLE_DATA_SOURCE = new InjectionToken('rxap/data-source/table/source');
const RXAP_TABLE_METHOD = new InjectionToken('rxap/data-source/table/table-method');
class AbstractTableDataSource extends AbstractPaginationDataSource {
constructor(paginator = null, sort = null, filter = null, parameters = null, metadata = null) {
super(paginator, metadata);
this.loading$ = new ToggleSubject(true);
if (parameters) {
this.parameters = parameters;
}
if (sort) {
this.sort = sort;
}
if (filter) {
this.filter = filter;
}
}
get sortByColumn() {
return this.sort?.active;
}
get sortDirection() {
return this.sort?.direction;
}
get totalRowCount() {
return this.paginator.length;
}
get filterValue() {
return this.filter?.current;
}
applySortBy(data, column, direction) {
return column ? data.slice().sort((a, b) => {
if (!hasIndexSignature(a) || !hasIndexSignature(b)) {
return 0;
}
const aColumn = a[column];
const bColumn = b[column];
const type = typeof aColumn;
let sort = 0;
switch (type) {
case 'boolean':
sort = aColumn === bColumn ? 0 : aColumn ? 1 : -1;
break;
case 'string':
sort = aColumn.localeCompare(bColumn);
break;
case 'number':
case 'bigint':
sort = aColumn - bColumn;
break;
}
return direction === 'desc' ? sort * -1 : sort;
}) : data.slice();
}
applyFilterBy(data, filter) {
if (filter) {
if (typeof filter === 'string') {
if (isDevMode()) {
console.error('The filter is a string. Currently not supported by the AbstractTableDataSource');
}
return data.slice();
}
else {
return data.filter(row => {
return Object.entries(filter).every(([key, value]) => {
const type = typeof value;
if (row[key] !== undefined && hasIndexSignature(row)) {
switch (type) {
case 'undefined':
return true;
case 'object':
return value === null || value === undefined || value === row[key];
case 'boolean':
return value === row[key];
case 'number':
return value === row[key];
case 'string':
return (row[key] || '').toString().toLowerCase().includes(value.toLowerCase());
case 'function':
return value(row[key]);
case 'bigint':
return value === row[key];
}
}
return true;
});
});
}
}
else {
return data.slice();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: AbstractTableDataSource, deps: [{ token: RXAP_TABLE_DATA_SOURCE_PAGINATOR, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_SORT, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_FILTER, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_PARAMETERS, optional: true }, { token: RXAP_DATA_SOURCE_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: AbstractTableDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: AbstractTableDataSource, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_PAGINATOR]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_SORT]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_FILTER]
}] }, { type: i1.Observable, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_PARAMETERS]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_DATA_SOURCE_METADATA]
}] }] });
function RxapAbstractTableDataSource(metadataOrId, className = 'AbstractTableDataSource', packageName = '@rxap/data-source/table') {
return function (target) {
RxapAbstractPaginationDataSource(metadataOrId, className, packageName)(target);
};
}
/**
* @deprecated removed use RXAP_TABLE_METHOD instead
*/
const RXAP_TABLE_REMOTE_METHOD = new InjectionToken('rxap/data-source/table/remote-method');
class DynamicTableDataSource extends AbstractTableDataSource {
constructor(method, paginator = null, sort = null, filter = null, parameters = null, metadata = method.metadata) {
super(paginator, sort, filter, parameters, metadata);
this.method = method;
this.paginatorMap = new Map();
this.sortMap = new Map();
this.filterMap = new Map();
this.parametersMap = new Map();
this._refresh$ = new BehaviorSubject(Date.now());
}
/**
* @deprecated use method instead
* @private
*/
get remoteMethod() {
return this.method;
}
// eslint-disable-next-line @angular-eslint/contextual-lifecycle
ngOnInit() {
this._data$ = this.createTableDataLoader(this.paginator, this.sort, this.filter, this.parameters);
}
setTotalLengthFactory(id) {
const paginator = id ? this.paginatorMap.get(id) : this.paginator;
function setTotalLength(length) {
if (paginator) {
paginator.length = length;
}
}
return setTotalLength;
}
setTotalLength(length, id) {
if (id) {
if (this.paginatorMap.has(id)) {
this.paginatorMap.get(id).length = length;
}
}
else {
if (this.paginator) {
this.paginator.length = length;
}
}
}
refresh() {
this._refresh$.next(Date.now());
}
setPaginator(paginator, id) {
if (paginator) {
if (id) {
this.paginatorMap.set(id, paginator);
}
else {
this.paginator = paginator;
}
}
}
setSort(sort, id) {
if (sort) {
if (id) {
this.sortMap.set(id, sort);
}
else {
this.sort = sort;
}
}
}
setFilter(tableFilter, id) {
if (tableFilter) {
if (id) {
this.filterMap.set(id, tableFilter);
}
else {
this.filter = tableFilter;
}
}
}
setParameters(parameters, id) {
if (parameters) {
if (id) {
this.parametersMap.set(id, parameters);
}
else {
this.parameters = parameters;
}
}
}
genericRetryFunction(error, retryCount) {
this.loading$.disable();
return super.genericRetryFunction(error, retryCount);
}
_connect(viewer) {
// call to ensure all parent logic is executed
let data = super._connect(viewer);
if (viewer.id && this.hasDynamicInputs(viewer.id)) {
data = this.createTableDataLoader(this.paginatorMap.get(viewer.id), this.sortMap.get(viewer.id), this.filterMap.get(viewer.id), this.parametersMap.get(viewer.id), viewer.id);
}
return data;
}
_disconnect(viewerId) {
if (this.hasDynamicInputs(viewerId)) {
this.paginatorMap.delete(viewerId);
this.sortMap.delete(viewerId);
this.filterMap.delete(viewerId);
this.parametersMap.delete(viewerId);
}
super._disconnect(viewerId);
}
async loadPage(tableEvent) {
try {
return await this.method.call(tableEvent);
}
catch (e) {
console.error(`Failed to load page: ${e.message}`);
this.handelError(e);
this.hasError$.enable();
this.error$.next(e);
}
return [];
}
handelError(error) {
if (isDevMode()) {
console.error(`Failed to load page: ${error.message}`, error);
}
}
hasDynamicInputs(id) {
return this.paginatorMap.has(id) || this.sortMap.has(id) || this.filterMap.has(id) || this.parametersMap.has(id);
}
createTableDataLoader(paginatorLike, sortLike, filterLike, parametersLike, id) {
return combineLatest([
paginatorLike?.page?.pipe(startWith({
pageIndex: paginatorLike?.pageIndex ?? 0,
pageSize: paginatorLike?.pageSize ?? Number.MAX_SAFE_INTEGER,
length: paginatorLike?.length,
})) ?? of(undefined),
sortLike?.sortChange?.pipe(startWith({
active: sortLike?.active,
direction: sortLike?.direction,
})) ?? of(undefined),
filterLike?.change?.pipe(tap(() => paginatorLike?.firstPage && paginatorLike?.firstPage())) ?? of(undefined),
parametersLike ?? of(undefined),
this._refresh$,
this._retry$.pipe(startWith(null)),
]).pipe(debounceTime(100), map(([page, sort, filter, parameters, refresh]) => {
const tableEvent = {
page,
start: page ? page.pageSize * page.pageIndex : 0,
end: page ? page.pageSize * page.pageIndex + page.pageSize : Number.MAX_SAFE_INTEGER,
sort,
filter,
parameters,
refresh,
};
return {
...clone(tableEvent),
setTotalLength: this.setTotalLengthFactory(id),
};
}), distinctUntilChanged((a, b) => equals(a, b)), tap(() => {
this.loading$.enable();
if (this.hasError$.value) {
this.hasError$.disable();
}
}), switchMap(tableEvent => this.loadPage(tableEvent)), tap({
next: () => this.loading$.disable(),
error: error => {
this.hasError$.enable();
this.error$.next(error);
this.handelError(error);
},
}), retry({
delay: (error, retryCount) => this.genericRetryFunction(error, retryCount),
}));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DynamicTableDataSource, deps: [{ token: RXAP_TABLE_METHOD, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_PAGINATOR, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_SORT, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_FILTER, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_PARAMETERS, optional: true }, { token: RXAP_DATA_SOURCE_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DynamicTableDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DynamicTableDataSource, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_METHOD]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_PAGINATOR]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_SORT]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_FILTER]
}] }, { type: i1.Observable, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_PARAMETERS]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_DATA_SOURCE_METADATA]
}] }] });
class RxapTableDataSourceError extends RxapDataSourceError {
constructor(message, code, className) {
super(message, code, className);
this.addSubPackageName('table');
}
}
class TableDataSource extends AbstractTableDataSource {
constructor(dataSource, paginator = null, sort = null, filter = null, parameters = null, metadata = dataSource.metadata) {
super(paginator, sort, filter, parameters, metadata);
this.dataSource = dataSource;
}
refresh() {
this.dataSource.refresh();
}
_connect(viewer) {
return [
this.dataSource.connect(viewer).pipe(tap((data) => this.updateTotalLength(data.length)), tap(() => this.loading$.disable()), switchMap((data) => {
this.assertPaginator();
if (this.paginator && this.paginator.page) {
return combineLatest([
this.paginator.page.pipe(startWith({
pageIndex: this.paginator.pageIndex,
pageSize: this.paginator.pageSize,
length: this.paginator.length,
})),
this.sort?.sortChange?.pipe(startWith({
active: this.sort?.active,
direction: this.sort?.direction,
})) ?? of(null),
this.filter?.change.pipe(startWith({})) ?? of(null),
]).pipe(map(([page, sort, filter]) => {
let filteredData = data;
if (filter) {
filteredData = this.applyFilterBy(filteredData, filter);
}
let sortData = filteredData;
if (sort) {
sortData = this.applySortBy(sortData, sort.active, sort.direction);
}
return this.applyPagination(sortData, page.pageSize, page.pageIndex);
}));
}
throw new Error('The paginator have not a defined page property!');
})),
() => this.dataSource.disconnect(viewer),
];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TableDataSource, deps: [{ token: RXAP_TABLE_DATA_SOURCE }, { token: RXAP_TABLE_DATA_SOURCE_PAGINATOR, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_SORT, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_FILTER, optional: true }, { token: RXAP_TABLE_DATA_SOURCE_PARAMETERS, optional: true }, { token: RXAP_DATA_SOURCE_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TableDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TableDataSource, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1$1.BaseDataSource, decorators: [{
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_PAGINATOR]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_SORT]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_FILTER]
}] }, { type: i1.Observable, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_TABLE_DATA_SOURCE_PARAMETERS]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [RXAP_DATA_SOURCE_METADATA]
}] }] });
function RxapTableDataSource(metadataOrId, className = 'TableDataSource', packageName = '@rxap/data-source/table') {
return function (target) {
RxapAbstractTableDataSource(metadataOrId, className, packageName)(target);
};
}
class ToTableDataSourcePipe {
transform(dataSource, paginator, sort, filter) {
return new TableDataSource(dataSource, paginator, sort, filter);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: ToTableDataSourcePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.1", ngImport: i0, type: ToTableDataSourcePipe, isStandalone: true, name: "toTableDataSource" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: ToTableDataSourcePipe, decorators: [{
type: Pipe,
args: [{
name: 'toTableDataSource',
standalone: true,
}]
}] });
// region
// endregion
/**
* Generated bundle index. Do not edit.
*/
export { AbstractTableDataSource, DynamicTableDataSource, RXAP_TABLE_DATA_SOURCE, RXAP_TABLE_DATA_SOURCE_FILTER, RXAP_TABLE_DATA_SOURCE_PAGINATOR, RXAP_TABLE_DATA_SOURCE_PARAMETERS, RXAP_TABLE_DATA_SOURCE_SORT, RXAP_TABLE_METHOD, RXAP_TABLE_REMOTE_METHOD, RxapAbstractTableDataSource, RxapTableDataSource, RxapTableDataSourceError, TableDataSource, ToTableDataSourcePipe };
//# sourceMappingURL=rxap-data-source-table.mjs.map