@igo2/common
Version:
267 lines (259 loc) • 20.8 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, ViewChild, Output, Input, Component, NgModule } from '@angular/core';
import { SelectionModel } from '@angular/cdk/collections';
import { NgIf, NgFor, NgClass } from '@angular/common';
import * as i6 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i5 from '@angular/material/checkbox';
import { MatCheckboxModule } from '@angular/material/checkbox';
import * as i1 from '@angular/material/form-field';
import { MatFormFieldModule } from '@angular/material/form-field';
import * as i7 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i2 from '@angular/material/input';
import { MatInputModule } from '@angular/material/input';
import * as i4 from '@angular/material/sort';
import { MatSortModule, MatSort } from '@angular/material/sort';
import * as i3 from '@angular/material/table';
import { MatTableModule } from '@angular/material/table';
import { IgoLanguageModule } from '@igo2/core/language';
import { ObjectUtils } from '@igo2/utils';
import { BehaviorSubject, merge, fromEvent } from 'rxjs';
import { map, debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { DataSource } from '@angular/cdk/table';
import * as i8 from '@ngx-translate/core';
var TableActionColor;
(function (TableActionColor) {
TableActionColor[TableActionColor["primary"] = 0] = "primary";
TableActionColor[TableActionColor["accent"] = 1] = "accent";
TableActionColor[TableActionColor["warn"] = 2] = "warn";
})(TableActionColor || (TableActionColor = {}));
class TableDatabase {
/** Stream that emits whenever the data has been modified. */
dataChange = new BehaviorSubject([]);
get data() {
return this.dataChange.value;
}
constructor(data) {
if (data) {
this.dataChange.next(data);
}
}
set(data) {
this.dataChange.next(data);
}
add(item) {
const copiedData = this.data.slice();
copiedData.push(item);
this.set(copiedData);
}
remove(item) {
const copiedData = this.data.slice();
const index = copiedData.indexOf(item);
copiedData.splice(index, 1);
this.set(copiedData);
}
}
class TableDataSource extends DataSource {
_database;
_model;
_sort;
get filter() {
return this._filterChange.value;
}
set filter(filter) {
this._filterChange.next(filter);
}
_filterChange = new BehaviorSubject('');
constructor(_database, _model, _sort) {
super();
this._database = _database;
this._model = _model;
this._sort = _sort;
}
// Connect function called by the table to retrieve one stream containing
// the data to render.
connect() {
if (!this._database) {
return merge([]);
}
const displayDataChanges = [
this._database.dataChange,
this._filterChange,
this._sort.sortChange
];
return merge(...displayDataChanges).pipe(map(() => {
return this.getFilteredData(this._database.data);
}), map((data) => {
return this.getSortedData(data);
}));
}
disconnect() {
// empty
}
getFilteredData(data) {
if (!this.filter) {
return data;
}
return data.slice().filter((item) => {
const searchStr = this._model.columns
.filter((c) => c.filterable)
.map((c) => ObjectUtils.resolve(item, c.name))
.join(' ')
.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
}
getSortedData(data) {
if (!this._sort.active || this._sort.direction === '') {
return data;
}
return data.sort((a, b) => {
const propertyA = ObjectUtils.resolve(a, this._sort.active);
const propertyB = ObjectUtils.resolve(b, this._sort.active);
return ObjectUtils.naturalCompare(propertyB, propertyA, this._sort.direction);
});
}
}
class TableComponent {
get database() {
return this._database;
}
set database(value) {
this._database = value;
}
_database;
get model() {
return this._model;
}
set model(value) {
this._model = value;
}
_model;
get hasFilterInput() {
return this._hasFIlterInput;
}
set hasFilterInput(value) {
this._hasFIlterInput = value;
}
_hasFIlterInput = true;
displayedColumns;
dataSource;
selection = new SelectionModel(true, []);
select = new EventEmitter();
filter;
sort;
ngOnInit() {
this.dataSource = new TableDataSource(this.database, this.model, this.sort);
if (this.model) {
this.displayedColumns = this.model.columns
.filter((c) => c.displayed !== false)
.map((c) => c.name);
if (this.model.selectionCheckbox) {
this.displayedColumns.unshift('selectionCheckbox');
}
if (this.model.actions && this.model.actions.length) {
this.displayedColumns.push('action');
}
}
this.selection.changed.subscribe((e) => this.select.emit(e));
}
ngAfterViewInit() {
if (this.filter) {
fromEvent(this.filter.nativeElement, 'keyup')
.pipe(debounceTime(150), distinctUntilChanged())
.subscribe(() => {
if (!this.dataSource) {
return;
}
this.dataSource.filter = this.filter.nativeElement.value;
});
}
}
ngOnChanges(change) {
if (change.database) {
this.dataSource = new TableDataSource(this.database, this.model, this.sort);
this.selection.clear();
}
}
getActionColor(colorId) {
return TableActionColor[colorId];
}
getValue(row, key) {
return ObjectUtils.resolve(row, key);
}
/** Whether the number of selected elements matches the total number of rows. */
isAllSelected() {
const numSelected = this.selection.selected.length;
const numRows = this.database.data.length;
return numSelected === numRows;
}
/** Selects all rows if they are not all selected; otherwise clear selection. */
masterToggle() {
this.isAllSelected()
? this.selection.clear()
: this.database.data.forEach((row) => this.selection.select(row));
}
handleClickAction(event, action, row) {
event.stopPropagation();
action.click(row);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: TableComponent, isStandalone: true, selector: "igo-table", inputs: { database: "database", model: "model", hasFilterInput: "hasFilterInput" }, outputs: { select: "select" }, viewQueries: [{ propertyName: "filter", first: true, predicate: ["filter"], descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"table-box\">\n <div class=\"table-header\" *ngIf=\"hasFilterInput\">\n <mat-form-field floatPlaceholder=\"never\">\n <input\n matInput\n #filter\n [placeholder]=\"'igo.common.table.filter' | translate\"\n />\n </mat-form-field>\n </div>\n\n <div class=\"table-container\">\n <table mat-table #table [dataSource]=\"dataSource\" matSort>\n <!-- Checkbox Column -->\n <ng-container matColumnDef=\"selectionCheckbox\">\n <th mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n >\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null\"\n [checked]=\"selection.isSelected(row)\"\n >\n </mat-checkbox>\n </td>\n </ng-container>\n\n <ng-container\n [matColumnDef]=\"column.name\"\n *ngFor=\"let column of model.columns\"\n >\n <ng-container *ngIf=\"column.sortable\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n {{ column.title }}\n </th>\n </ng-container>\n\n <ng-container *ngIf=\"!column.sortable\">\n <th mat-header-cell *matHeaderCellDef>{{ column.title }}</th>\n </ng-container>\n\n <ng-container *ngIf=\"!column.html; else cellHTML\">\n <td\n mat-cell\n *matCellDef=\"let row\"\n class=\"mat-cell-text\"\n [ngClass]=\"\n model.cellClassFunc ? model.cellClassFunc(row, column) : {}\n \"\n >\n {{ getValue(row, column.name) }}\n </td>\n </ng-container>\n\n <ng-template #cellHTML>\n <td\n mat-cell\n *matCellDef=\"let row\"\n class=\"mat-cell-text\"\n [ngClass]=\"\n model.cellClassFunc ? model.cellClassFunc(row, column) : {}\n \"\n [innerHTML]=\"getValue(row, column.name)\"\n ></td>\n </ng-template>\n </ng-container>\n\n <!-- Action Column -->\n <ng-container matColumnDef=\"action\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <button\n *ngFor=\"let action of model.actions\"\n mat-mini-fab\n [color]=\"getActionColor(action.color)\"\n (click)=\"handleClickAction($event, action, row)\"\n >\n <mat-icon>{{ action.icon }}</mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [ngClass]=\"model.rowClassFunc ? model.rowClassFunc(row) : {}\"\n (click)=\"selection.toggle(row)\"\n ></tr>\n </table>\n </div>\n</div>\n", styles: [":host{width:100%;height:100%;display:block}.table-container{display:flex;flex-direction:column;height:100%;overflow:auto;flex:1 1 auto}.table-box{height:100%;display:flex;flex-direction:column}.table-header{min-height:64px;max-width:500px;display:flex;flex:0 1 auto;align-items:baseline;padding:8px 24px 0;font-size:20px;justify-content:space-between}tr[mat-header-row],tr[mat-row]{height:60px}.mat-cell-text{overflow:hidden;word-wrap:break-word}td[mat-cell]{padding-right:15px}th.mat-mdc-header-cell{padding-right:5px}button{margin-right:10px}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i3.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i3.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i3.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i3.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i3.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i3.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i3.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i3.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i3.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i3.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i4.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i4.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatMiniFabButton, selector: "button[mat-mini-fab]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: IgoLanguageModule }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TableComponent, decorators: [{
type: Component,
args: [{ selector: 'igo-table', imports: [
NgIf,
MatFormFieldModule,
MatInputModule,
MatTableModule,
MatSortModule,
MatCheckboxModule,
NgFor,
NgClass,
MatButtonModule,
MatIconModule,
IgoLanguageModule
], template: "<div class=\"table-box\">\n <div class=\"table-header\" *ngIf=\"hasFilterInput\">\n <mat-form-field floatPlaceholder=\"never\">\n <input\n matInput\n #filter\n [placeholder]=\"'igo.common.table.filter' | translate\"\n />\n </mat-form-field>\n </div>\n\n <div class=\"table-container\">\n <table mat-table #table [dataSource]=\"dataSource\" matSort>\n <!-- Checkbox Column -->\n <ng-container matColumnDef=\"selectionCheckbox\">\n <th mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n >\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null\"\n [checked]=\"selection.isSelected(row)\"\n >\n </mat-checkbox>\n </td>\n </ng-container>\n\n <ng-container\n [matColumnDef]=\"column.name\"\n *ngFor=\"let column of model.columns\"\n >\n <ng-container *ngIf=\"column.sortable\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n {{ column.title }}\n </th>\n </ng-container>\n\n <ng-container *ngIf=\"!column.sortable\">\n <th mat-header-cell *matHeaderCellDef>{{ column.title }}</th>\n </ng-container>\n\n <ng-container *ngIf=\"!column.html; else cellHTML\">\n <td\n mat-cell\n *matCellDef=\"let row\"\n class=\"mat-cell-text\"\n [ngClass]=\"\n model.cellClassFunc ? model.cellClassFunc(row, column) : {}\n \"\n >\n {{ getValue(row, column.name) }}\n </td>\n </ng-container>\n\n <ng-template #cellHTML>\n <td\n mat-cell\n *matCellDef=\"let row\"\n class=\"mat-cell-text\"\n [ngClass]=\"\n model.cellClassFunc ? model.cellClassFunc(row, column) : {}\n \"\n [innerHTML]=\"getValue(row, column.name)\"\n ></td>\n </ng-template>\n </ng-container>\n\n <!-- Action Column -->\n <ng-container matColumnDef=\"action\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <button\n *ngFor=\"let action of model.actions\"\n mat-mini-fab\n [color]=\"getActionColor(action.color)\"\n (click)=\"handleClickAction($event, action, row)\"\n >\n <mat-icon>{{ action.icon }}</mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [ngClass]=\"model.rowClassFunc ? model.rowClassFunc(row) : {}\"\n (click)=\"selection.toggle(row)\"\n ></tr>\n </table>\n </div>\n</div>\n", styles: [":host{width:100%;height:100%;display:block}.table-container{display:flex;flex-direction:column;height:100%;overflow:auto;flex:1 1 auto}.table-box{height:100%;display:flex;flex-direction:column}.table-header{min-height:64px;max-width:500px;display:flex;flex:0 1 auto;align-items:baseline;padding:8px 24px 0;font-size:20px;justify-content:space-between}tr[mat-header-row],tr[mat-row]{height:60px}.mat-cell-text{overflow:hidden;word-wrap:break-word}td[mat-cell]{padding-right:15px}th.mat-mdc-header-cell{padding-right:5px}button{margin-right:10px}\n"] }]
}], propDecorators: { database: [{
type: Input
}], model: [{
type: Input
}], hasFilterInput: [{
type: Input
}], select: [{
type: Output
}], filter: [{
type: ViewChild,
args: ['filter']
}], sort: [{
type: ViewChild,
args: [MatSort, { static: true }]
}] } });
/**
* @deprecated import the TableComponent directly
*/
class IgoTableModule {
static forRoot() {
return {
ngModule: IgoTableModule,
providers: []
};
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoTableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.15", ngImport: i0, type: IgoTableModule, imports: [TableComponent], exports: [TableComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoTableModule, imports: [TableComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoTableModule, decorators: [{
type: NgModule,
args: [{
imports: [TableComponent],
exports: [TableComponent]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { IgoTableModule, TableActionColor, TableComponent, TableDataSource, TableDatabase };
//# sourceMappingURL=igo2-common-table.mjs.map