UNPKG

ngx-advanced-material-table

Version:

Advanced Angular Material Table component, along with many features such as filter and display/hide columns

559 lines 110 kB
import * as _ from 'lodash'; // FIXME(Fernando Abel): XLSX module not being found // import * as xlsx from 'xlsx'; import { Component, Input, ViewChild, EventEmitter, Output } from '@angular/core'; import { MatSort } from '@angular/material/sort'; import { take } from 'rxjs/operators'; import { ColumnType, } from './interfaces/column-definition.interface'; import { MatPaginator } from '@angular/material/paginator'; import { MatTableDataSource } from '@angular/material/table'; import { SelectionModel } from '@angular/cdk/collections'; import { TableBuilderHelper } from './helpers/table-builder.helper'; import { Value } from './helpers/values.helper'; import { FilterColumnsComponent } from './components/filter-columns/filter-columns.component'; import { ColumnHelper } from './helpers/columns.helper'; import * as i0 from "@angular/core"; import * as i1 from "@angular/material/dialog"; import * as i2 from "./services/local-storage.service"; import * as i3 from "@angular/material/form-field"; import * as i4 from "@angular/material/button"; import * as i5 from "@angular/material/icon"; import * as i6 from "@angular/material/menu"; import * as i7 from "@angular/material/paginator"; import * as i8 from "@angular/material/table"; import * as i9 from "@angular/material/checkbox"; import * as i10 from "@angular/material/sort"; import * as i11 from "@angular/common"; import * as i12 from "@angular/material/input"; import * as i13 from "@angular/material/tooltip"; import * as i14 from "@angular/cdk/drag-drop"; export class AdvancedMaterialTableComponent { constructor(dialog, localStorageService, cdref) { this.dialog = dialog; this.localStorageService = localStorageService; this.cdref = cdref; this.actionSelected = new EventEmitter(); this.iconClicked = new EventEmitter(); this.rowSelected = new EventEmitter(); this.numberChange = new EventEmitter(); this.hyperLinkClicked = new EventEmitter(); this.displayedColumns = []; this.noRowsDisplayed = false; this.hasHiddenColumns = false; this.columnType = ColumnType; this.selection = new SelectionModel(true, []); this.tableColumnList = []; this.mainFilter = ''; this.getContent = (column, element) => ColumnHelper.getContent(column.Field, element); this.getToolTip = (row, column) => ColumnHelper.getToolTip(column, row); //#endregion //#region Checks (Header, Cell, Column or Row) this.isImmutableColumn = ColumnHelper.isImmutableColumn; this.canColumnBeHidden = ColumnHelper.canColumnBeHidden; this.canColumnBeMoved = ColumnHelper.canColumnBeMoved; this.canColumnBeFiltered = ColumnHelper.canColumnBeFiltered; this.isFilteringEnabledOnColumn = ColumnHelper.isFilteringEnabledOnColumn; this.hasFiltersOrSortingEnabled = ColumnHelper.hasFiltersOrSortingEnabled; this.isCellClickable = ColumnHelper.isCellClickable; } set tableColumns(value) { this.tableColumnList = _.cloneDeep(value); } get tableColumns() { return this.tableColumnList; } set data(value) { this.dataset = value; this.initializeTable(); } get data() { return this.dataset; } set selectedData(initialSelection) { this.selection = new SelectionModel(true, initialSelection); } get selectedData() { return this.selection.selected; } ngOnInit() { this.loadFromStorage(); this.renderColumns(); this.localizePaginator(); } ngAfterViewInit() { this.sortColumns(); this.sort.sortChange.subscribe((col) => { if (!col.active) { return; } this.tableColumnList.forEach((column) => { if (column.Field !== col.active) { column.SortDirection = undefined; } else { column.SortDirection = col.direction; } }); }); this.initializeTable(); } initializeTable() { if (this.data) { this.noRowsDisplayed = this.data.length === 0; } this.dataSource = new MatTableDataSource(this.data); this.dataSource.paginator = this.paginator; this.dataSource.sortingDataAccessor = (item, property) => { const content = ColumnHelper.getContent(property, item); if (!content) { return ''; } return content.toString().toLowerCase(); }; this.dataSource.sort = this.sort; this.dataSource.filterPredicate = this.getFilterPredicate(); this.applyFilters(); } renderColumns() { this.displayedColumns = this.tableColumns.filter((column) => column.Display === true).map((column) => column.Field); if (this.tableConfiguration.AllowSelect) { // Add the 'select' column at the start this.displayedColumns.unshift('select'); } } onRowChecked(row) { if (this.tableConfiguration.MultipleSelect) { this.multipleRowSelection(row); } else { this.singleRowSelection(row); } this.rowSelected.emit([false, this.selection.selected]); } onDoubleClick(row) { this.rowSelected.emit([true, [row]]); } masterToggle() { this.isAllSelected() ? this.selection.clear() : this.dataSource.data.forEach((row) => this.selection.select(row)); this.rowSelected.emit([false, this.selection.selected]); } isAllSelected() { const numSelected = this.selection.selected.length; const numRows = this.dataSource.data.length; return numSelected === numRows; } getFilterPredicate() { return (row, filters) => { const filterData = JSON.parse(filters); for (const filter of filterData) { if (filter.values.length === 0) { continue; } let value = _.get(row, filter.key); if (!value || value === '') { return false; } let index = -1; if (filter.type === ColumnType.DateTime || filter.type === ColumnType.Date) { const dates = filter.values.map((x) => new Date(x)); index = dates.findIndex((x) => x.getTime() === value.getTime()); } else if (Value.isArray(value)) { value = _.join(value, ','); index = filter.values.findIndex((x) => _.isEqual(x, value)); } else { index = filter.values.findIndex((x) => _.isEqual(x, value)); } if (index === -1) { return false; } } if (this.mainFilter && this.mainFilter.length > 0) { let match = false; filterData.forEach((filter) => { const value = _.get(row, filter.key); const stringValue = value.toLowerCase(); match = match || stringValue.indexOf(this.mainFilter) !== -1; }); return match; } return true; }; } onColumnChange(index, event) { if (this.tableColumns[index].Display && this.tableColumns.filter((c) => c.Display).length <= 1) { event.preventDefault(); return; } this.tableColumns[index].Display = !this.tableColumns[index].Display; this.renderColumns(); this.saveColumnConfig(); } clearAllFilters() { this.tableColumnList.forEach((column) => { column.SortDirection = undefined; column.FilterValues = undefined; }); // Clear sort, see https://github.com/angular/components/issues/10524 this.clearSort(); this.dataSource.filter = '[]'; } /** * Return from the Action Buttons * @param action Value From the Action Buttons */ onActionSelected(action) { this.actionSelected.emit(action); } getMinValueForNumberInput(element, column) { if (!column || !column.NumberInputOptions) { return; } if (column.NumberInputOptions.MinInputNumberField) { return element[column.NumberInputOptions.MinInputNumberField]; } return column.NumberInputOptions.MinInputNumber; } getMaxValueForNumberInput(element, column) { if (!column.NumberInputOptions) { return; } if (column.NumberInputOptions.MaxInputNumberField) { return element[column.NumberInputOptions.MaxInputNumberField]; } return column.NumberInputOptions.MaxInputNumber; } iconClick(element, column) { this.iconClicked.emit([element, column]); } numberInputChange(element, column, event) { this.numberChange.emit([element, column, event.target.value]); } onHyperLinkClicked(element, column) { this.hyperLinkClicked.emit([element, column]); } multipleRowSelection(row) { this.selection.toggle(row); } singleRowSelection(row) { if (this.selection.isSelected(row)) { this.selection.clear(); } else { this.selection.clear(); this.selection.toggle(row); } } getDistinctValues(selectedColumn) { let result = []; this.data.forEach((row) => { let value = _.get(row, selectedColumn.Field); let displayedValue = value; if (Value.isArray(value)) { value = _.join(value, ','); displayedValue = value; } if (value === undefined || value === null || value === '') { return; } const isAlreadyChecked = selectedColumn.FilterValues ? selectedColumn.FilterValues.findIndex((x) => x === value) >= 0 : false; result.push({ name: value, displayedName: displayedValue, checked: isAlreadyChecked, }); }); result = _.uniqBy(result, (x) => x.displayedName); return result; } //#region Drag and Drop headerDragStarted(index) { // Purposedly in blank } headerDropListDropped(event) { if (!event) { return; } const displayedColumns = this.displayedColumns.filter((x) => x != 'select'); const previousColumnIndex = this.tableColumns.findIndex((x) => x.Field === displayedColumns[event.previousIndex]); const currentColumnIndex = this.tableColumns.findIndex((x) => x.Field === displayedColumns[event.currentIndex]); if (this.canColumnBeMoved(this.tableColumns[currentColumnIndex])) { this.moveItemInArray(this.tableColumns, previousColumnIndex, currentColumnIndex); this.renderColumns(); this.saveColumnConfig(); } } //#endregion //#region Sorting and Filtering applyMainFilter(event) { this.mainFilter = event.value.trim().toLowerCase(); this.applyFilters(); } applyFilters() { const filters = []; this.tableColumnList.forEach((column) => { if (!column.FilterValues) { column.FilterValues = []; } filters.push({ key: column.Field, type: column.ColumnType, values: column.FilterValues, }); }); if (filters.length > 0) { this.dataSource.filter = JSON.stringify(filters); } } sortColumn(id, start) { const currentColumn = this.sort.active; const currentDirection = this.sort.direction; if (id !== currentColumn || start !== currentDirection) { this.sort.sort({ id: '', start, disableClear: false }); this.sort.sort({ id, start, disableClear: false }); } } clearSort() { // Clear sort, see https://github.com/angular/components/issues/10524 let sortable = { id: null, start: null, disableClear: false }; this.sort.sort(sortable); } sortColumns() { const id = this.tableColumns.findIndex((column) => column.SortDirection); if (id === -1) { return; } const columnName = this.tableColumns[id].Field; const direction = this.tableColumns[id].SortDirection; this.clearSort(); if (direction) { this.sortColumn(columnName, direction); } // HACK(Fernando Abel): https://github.com/angular/components/issues/10242 const activeSortHeader = this.sort.sortables.get(columnName); if (activeSortHeader) { const viewState = activeSortHeader._isSorted() ? { fromState: direction, toState: 'active' } : { fromState: 'active', toState: direction }; activeSortHeader._setAnimationTransitionState(viewState); } this.cdref.detectChanges(); } //#endregion //#region Dialogs openFilterDialog(selectedColumn) { const data = { selectedColumn: _.cloneDeep(selectedColumn), distinctData: this.getDistinctValues(selectedColumn), }; const columnFilteringDialog = this.dialog.open(FilterColumnsComponent, { disableClose: false, autoFocus: false, width: '350px', panelClass: 'overlay-panel', data, }); columnFilteringDialog .afterClosed() .pipe(take(1)) .subscribe((response) => { if (response && response.action === 'Ok') { this.filterByColumn(response); this.sortByTable(response); } }); } //#endregion //#region After FilterColumns response filterByColumn(response) { if (!response || !response.selectedColumn) { return; } const column = this.tableColumnList.find((x) => x.Field === response.selectedColumn.Field); if (column) { column.FilterValues = response.selectedColumn.FilterValues; } this.applyFilters(); } sortByTable(response) { if (response.sortingHasChanged === false) { return; } const columnName = response.selectedColumn.Field; const direction = response.selectedColumn.SortDirection; this.tableColumnList.forEach((column) => { column.SortDirection = column.Field !== columnName ? undefined : direction; }); this.sortColumns(); } //#endregion //#region Print and Export sendToPrinter() { const selectedData = this.getDataToExportPrint(); const colNames = this.getDisplayedColumnNames(); const table = TableBuilderHelper.buildTable(selectedData, this.displayedColumns, colNames); if (table) { const newWin = window.open('#'); if (!newWin) return; newWin.document.write(TableBuilderHelper.printPageBuilderDefault(table)); newWin.print(); newWin.close(); } } // TODO: Create a service for that, currently being used in advanced table exportToExcel() { // const tableTitle = TableTags.Table; // const selectedData = this.getSelectedDataWithDisplayedColumnsOnly(); // const colNames = this.getDisplayedColumnNames(); // // generate a worksheet // const ws = xlsx.utils.aoa_to_sheet([colNames]); // xlsx.utils.sheet_add_json(ws, selectedData, { // header: this.displayedColumns.slice(1), // remove the 'select' column // skipHeader: true, // origin: 1, // }); // // add to workbook // const wb = xlsx.utils.book_new(); // xlsx.utils.book_append_sheet(wb, ws, tableTitle); // // write workbook and force a download // xlsx.writeFile(wb, `${tableTitle}.xls`, { // type: 'array', // bookType: 'xls', // }); } getDataToExportPrint() { if (!this.selection.isEmpty()) { return this.selection.selected; } if (!this.dataSource.sort) { return this.selection.selected; } return this.dataSource.sortData(this.dataSource.filteredData, this.dataSource.sort); } getSelectedDataWithDisplayedColumnsOnly() { const selectedData = this.getDataToExportPrint(); return _.map(selectedData, (obj) => { return _.pick(obj, this.displayedColumns); }); } getDisplayedColumnNames() { return this.tableColumns.filter((column) => column.Display === true).map((column) => column.Title); } //#endregion //#region LocalStorage loadFromStorage() { if (!this.tableConfiguration || !this.tableConfiguration.LocalStorageKey) { return; } const localStorageColumns = this.localStorageService.getAsJson(this.tableConfiguration.LocalStorageKey); if (!localStorageColumns) { return; } const tableColumnList = _.cloneDeep(this.tableColumns); for (const obj of tableColumnList) { const index = localStorageColumns.findIndex((i) => i.Field === obj.Field); if (index !== -1) { const previousIndex = this.tableColumns.findIndex((i) => i.Field === obj.Field); // update the displayed property this.tableColumns[previousIndex].Display = localStorageColumns[index].Display; // rearange columns this.moveItemInArray(this.tableColumns, previousIndex, index); } } } saveColumnConfig() { if (!this.tableConfiguration || !this.tableConfiguration.LocalStorageKey) { return; } this.localStorageService.setAsJson(this.tableConfiguration.LocalStorageKey, this.tableColumns); } moveItemInArray(array, previousIndex, index) { const temp = array[previousIndex]; array[previousIndex] = array[index]; array[index] = temp; } //#endregion //#region Paginator localizePaginator() { if (!this.tableConfiguration.AllowPagination) { return; } if (this.paginator === undefined) { return; } this.paginator._intl.firstPageLabel = 'First Page'; this.paginator._intl.previousPageLabel = 'Previous Page'; this.paginator._intl.nextPageLabel = 'Next Page'; this.paginator._intl.lastPageLabel = 'Last Page'; this.paginator._intl.itemsPerPageLabel = 'Items per Page'; this.paginator._intl.getRangeLabel = (page, pageSize, length) => { if (length === 0 || pageSize === 0) { return `0 of ${length}`; } length = Math.max(length, 0); const startIndex = page * pageSize; // If the start index exceeds the list length, do not try and fix the end index to the end. const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize; return `${startIndex + 1} - ${endIndex} of ${length}`; }; } //#endregion //#region ClassNames getRowClassName() { const hasImageColumn = this.tableColumns.find((c) => c.ColumnType === ColumnType.Image); if (hasImageColumn) { return 'row-with-image'; } return ''; } getColumnClassName(column) { switch (column.ColumnType) { case ColumnType.Actions: return 'actions'; case ColumnType.Icon: return 'icons'; case ColumnType.Image: return 'images'; } return ''; } } AdvancedMaterialTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.12", ngImport: i0, type: AdvancedMaterialTableComponent, deps: [{ token: i1.MatDialog }, { token: i2.LocalStorageService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); AdvancedMaterialTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.12", type: AdvancedMaterialTableComponent, selector: "ngx-advanced-material-table", inputs: { tableConfiguration: "tableConfiguration", actionConfiguration: "actionConfiguration", tableColumns: "tableColumns", data: "data", selectedData: "selectedData" }, outputs: { actionSelected: "actionSelected", iconClicked: "iconClicked", rowSelected: "rowSelected", numberChange: "numberChange", hyperLinkClicked: "hyperLinkClicked" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }], ngImport: i0, template: "<div>\n <div class=\"table-top-panel\" *ngIf=\"tableConfiguration.AllowFilter || tableConfiguration.AllowActions\">\n <div class=\"table-filter\">\n <ng-container *ngIf=\"tableConfiguration.AllowFilter\">\n <mat-form-field>\n <input\n matInput\n id=\"{{ tableConfiguration.Id }}-table-filter-field\"\n (keyup)=\"applyMainFilter($event.target)\"\n i18n-placeholder=\"@@placeholder-text-filterResult\"\n placeholder=\"Filter on results...\"\n />\n </mat-form-field>\n </ng-container>\n </div>\n\n <div class=\"table-actions\" *ngIf=\"tableConfiguration.AllowActions\">\n <button\n mat-icon-button\n id=\"{{ tableConfiguration.Id }}-table-clearAllFilters\"\n onclick=\"this.blur()\"\n (click)=\"clearAllFilters()\"\n [matTooltip]=\"templateClearAllFilters.innerText\"\n >\n <mat-icon>filter_list_off</mat-icon>\n </button>\n\n <button\n mat-icon-button\n id=\"{{ tableConfiguration.Id }}-table-showColumns\"\n [matMenuTriggerFor]=\"visibleColumnsMenu\"\n [matTooltip]=\"templateShowHide.innerText\"\n >\n <mat-icon>view_column</mat-icon>\n </button>\n\n <mat-menu #visibleColumnsMenu=\"matMenu\">\n <ng-template matMenuContent>\n <div id=\"{{ tableConfiguration.Id }}-table-columns-checkbox\">\n <div\n mat-menu-item\n *ngFor=\"let column of tableColumns; let i = index\"\n (click)=\"onColumnChange(i, $event); $event.stopPropagation()\"\n >\n <mat-icon *ngIf=\"column.Display\" color=\"accent\">check_box</mat-icon>\n <mat-icon *ngIf=\"!column.Display\">check_box_outline_blank</mat-icon>\n <span>{{ column.Title }}</span>\n </div>\n </div>\n </ng-template>\n </mat-menu>\n\n <button\n mat-icon-button\n id=\"{{ tableConfiguration.Id }}-table-export-to-excel-button\"\n [matTooltip]=\"templateExportCsv.innerText\"\n (click)=\"exportToExcel()\"\n [disabled]=\"noRowsDisplayed\"\n >\n <mat-icon>file_download</mat-icon>\n </button>\n\n <button\n mat-icon-button\n id=\"{{ tableConfiguration.Id }}-table-print-button\"\n (click)=\"sendToPrinter()\"\n [matTooltip]=\"templatePrint.innerText\"\n [disabled]=\"noRowsDisplayed\"\n >\n <mat-icon>print</mat-icon>\n </button>\n\n <template #templateShowHide i18n=\"@@table-tooltip-grid-showColumns\">Select visible columns</template>\n <template #templateExportCsv i18n=\"@@table-tooltip-export-csv\">Export to Excel</template>\n <template #templateClearAllFilters i18n=\"@@table-tooltip-clear-all-filters\">Clear filters and sorting</template>\n <template #templatePrint i18n=\"@@action-btn-print\">Print</template>\n </div>\n </div>\n\n <div class=\"table-pagination\" *ngIf=\"tableConfiguration.AllowPagination\">\n <mat-paginator\n [pageSizeOptions]=\"[10, 25, 50, 100]\"\n id=\"{{ tableConfiguration.Id }}-table-paginator\"\n showFirstLastButtons\n ></mat-paginator>\n </div>\n\n <mat-table\n id=\"{{ tableConfiguration.Id }}-table\"\n [dataSource]=\"dataSource\"\n matSort\n matSortDisableClear=\"false\"\n cdkDropListGroup\n cdkDropList\n cdkDropListLockAxis=\"x\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"headerDropListDropped($event)\"\n >\n <!-- Select Check Box Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n *ngIf=\"tableConfiguration.MultipleSelect\"\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n >\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? onRowChecked(row) : null\"\n [checked]=\"selection.isSelected(row)\"\n >\n </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let column of tableColumns; let i = index\" matColumnDef=\"{{ column.Field }}\">\n <mat-header-cell\n *matHeaderCellDef\n cdkDrag\n (cdkDragStarted)=\"headerDragStarted(i)\"\n [cdkDragData]=\"{ name: column.Field }\"\n [cdkDragDisabled]=\"!canColumnBeMoved(column)\"\n [ngClass]=\"getColumnClassName(column)\"\n [matTooltip]=\"column.Title\"\n >\n <ng-container *ngIf=\"isFilteringEnabledOnColumn(column)\">\n <span mat-sort-header [class.selected]=\"hasFiltersOrSortingEnabled(column)\">{{ column.Title }}</span>\n <button\n mat-icon-button\n disableRipple\n onclick=\"this.blur()\"\n (click)=\"openFilterDialog(column)\"\n [disabled]=\"noRowsDisplayed\"\n [class.selected]=\"hasFiltersOrSortingEnabled(column)\"\n >\n <mat-icon>filter_list</mat-icon>\n </button>\n </ng-container>\n </mat-header-cell>\n <mat-cell\n *matCellDef=\"let element; let rowIndex = index\"\n [ngClass]=\"getColumnClassName(column)\"\n (click)=\"isCellClickable(column) ? onRowChecked(element) : null\"\n >\n <div [matTooltip]=\"getToolTip(element, column)\">\n <ng-container [ngSwitch]=\"column.ColumnType\">\n <!-- DateTime -->\n <span *ngSwitchCase=\"columnType.DateTime\"> {{ getContent(column, element) }}</span>\n <!-- Date -->\n <span *ngSwitchCase=\"columnType.Date\"> {{ getContent(column, element) }}</span>\n <!-- Time -->\n <span *ngSwitchCase=\"columnType.Time\"> {{ getContent(column, element) }}</span>\n <!-- String -->\n <span *ngSwitchCase=\"columnType.String\"> {{ getContent(column, element) }}</span>\n <!-- Link -->\n <span *ngSwitchCase=\"columnType.Link\" (click)=\"onHyperLinkClicked(element, column)\">\n <a href=\"{{ getContent(column, element) }}\" target=\"_blank\" rel=\"noopener\">{{ getContent(column, element) }}</a>\n </span>\n <!-- Image -->\n <div *ngSwitchCase=\"columnType.Image\">\n <img src=\"{{ getContent(column, element) }}\" alt=\"image\" />\n </div>\n <!-- Actions -->\n <!-- <ng-container *ngSwitchCase=\"columnType.Actions\">\n <app-advance-table-row-menu\n [rowData]=\"element\"\n [tableRowMenu]=\"RowActionsConfig\"\n (actionSelected)=\"onActionSelected($event)\"\n ></app-advance-table-row-menu>\n </ng-container> -->\n <!-- Dropdown -->\n <!-- <ng-container *ngSwitchCase=\"columnType.DropDown\">\n <app-advanced-table-row-dropdown\n [rowData]=\"element\"\n [columnData]=\"column\"\n [tableRowDropDown]=\"RowDropDownConfig\"\n (dropDownSelected)=\"onDropDownSelected($event)\"\n ></app-advanced-table-row-dropdown>\n </ng-container> -->\n <!-- Icon -->\n <ng-container *ngSwitchCase=\"columnType.Icon\">\n <button mat-icon-button (click)=\"iconClick(element, column)\">\n <mat-icon> {{ column.MatIconName }}</mat-icon>\n {{ getContent(column, element) }}\n </button>\n </ng-container>\n <!-- Number Input -->\n <ng-container *ngSwitchCase=\"columnType.NumberInput\">\n <mat-form-field floatLabel=\"never\">\n <input\n matInput\n onlyNumbers\n type=\"number\"\n [min]=\"getMinValueForNumberInput(element, column)\"\n [max]=\"getMaxValueForNumberInput(element, column)\"\n (change)=\"numberInputChange(element, column, $event)\"\n [value]=\"element[column.Field]\"\n />\n <!-- Suffix -->\n <span matSuffix class=\"suffix\" *ngIf=\"column.Suffix\">\n {{ element[column.Suffix.Field] }}\n </span>\n </mat-form-field>\n </ng-container>\n </ng-container>\n <!-- Suffix -->\n <span class=\"suffix\" *ngIf=\"column.Suffix && column.ColumnType !== columnType.NumberInput\">\n {{ element[column.Suffix.Field] }}\n </span>\n </div>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n id=\"{{ row.Id }}\"\n [ngClass]=\"getRowClassName()\"\n (dblclick)=\"onDoubleClick(row)\"\n ></mat-row>\n </mat-table>\n\n <div *ngIf=\"noRowsDisplayed\" class=\"no-records\">\n <span i18n=\"@@table-noResultFound\">No matching records found</span>\n </div>\n</div>\n", styles: [".mat-table{border:1px solid rgba(0,0,0,.12);border-bottom:0}.mat-header-row{min-height:40px;height:40px}.mat-row{min-height:40px;height:40px;align-items:stretch}.mat-row:hover{background-color:#4d74a8}.mat-row:hover .mat-cell,.mat-row:hover .mat-icon{color:#fff}.mat-row.row-with-image{height:55px}.mat-row .mat-cell>div{width:100%;display:flex;align-items:center}.mat-row .mat-cell .mat-form-field{min-width:50%}.mat-row .mat-cell img{height:55px;min-width:100px;margin:0}.mat-header-cell,.mat-cell{min-height:40px;border-right:1px solid rgba(0,0,0,.12);padding:0 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mat-header-cell.mat-column-select,.mat-cell.mat-column-select{padding:0 8px;width:20px;flex:none;justify-content:center}.mat-header-cell:last-child,.mat-cell:last-child{border-right:0}.no-records{height:48px;display:flex;align-items:center;justify-content:center;background:white}.table-top-panel{display:flex;justify-content:space-between;height:1.25em;padding:1em 0 1.5em}.table-actions{display:flex;justify-content:flex-end;align-items:center;flex:0 1 auto}.table-pagination{display:flex;justify-content:flex-end;align-items:center;flex:0 1 auto}.table-pagination h4{margin:0;text-transform:uppercase;font-weight:bold}.table-pagination .mat-paginator{background:transparent}.table-pagination .mat-form-field{width:4em;margin:0 .2em 0 .5em}.mat-header-cell{display:flex;align-items:inherit;align-content:stretch}.mat-header-cell .mat-icon{font-size:1em}.mat-header-cell span{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:bold}.mat-header-cell.icons,.mat-header-cell.actions,.mat-cell.icons,.mat-cell.actions{padding:0;width:40px;flex:none;justify-content:center}.mat-header-cell.images,.mat-cell.images{padding:2px;min-width:100px;flex:none;justify-content:center}\n"], components: [{ type: i3.MatFormField, selector: "mat-form-field", inputs: ["color", "floatLabel", "appearance", "hideRequiredMarker", "hintLabel"], exportAs: ["matFormField"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: i6.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { type: i7.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "id", "labelPosition", "name", "required", "checked", "disabled", "indeterminate", "aria-describedby", "value"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i10.MatSortHeader, selector: "[mat-sort-header]", inputs: ["disabled", "arrowPosition", "sortActionDescription", "disableClear", "mat-sort-header", "start"], exportAs: ["matSortHeader"] }, { type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }], directives: [{ type: i11.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["id", "disabled", "required", "type", "value", "readonly", "placeholder", "errorStateMatcher", "aria-describedby"], exportAs: ["matInput"] }, { type: i13.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i6.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { type: i6.MatMenuContent, selector: "ng-template[matMenuContent]" }, { type: i11.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i10.MatSort, selector: "[matSort]", inputs: ["matSortDisabled", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortActive"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { type: i14.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { type: i14.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "id", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListAutoScrollDisabled", "cdkDropListOrientation", "cdkDropListLockAxis", "cdkDropListData", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i8.MatCellDef, selector: "[matCellDef]" }, { type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i14.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragDisabled", "cdkDragStartDelay", "cdkDragLockAxis", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragBoundary", "cdkDragRootElement", "cdkDragPreviewContainer", "cdkDragData", "cdkDragFreeDragPosition"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { type: i11.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i11.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i11.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i3.MatSuffix, selector: "[matSuffix]" }, { type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.12", ngImport: i0, type: AdvancedMaterialTableComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-advanced-material-table', templateUrl: './ngx-advanced-material-table.component.html', styleUrls: ['./ngx-advanced-material-table.component.scss'], }] }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i2.LocalStorageService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { tableConfiguration: [{ type: Input }], actionConfiguration: [{ type: Input }], tableColumns: [{ type: Input }], data: [{ type: Input }], selectedData: [{ type: Input }], actionSelected: [{ type: Output }], iconClicked: [{ type: Output }], rowSelected: [{ type: Output }], numberChange: [{ type: Output }], hyperLinkClicked: [{ type: Output }], paginator: [{ type: ViewChild, args: [MatPaginator] }], sort: [{ type: ViewChild, args: [MatSort] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWFkdmFuY2VkLW1hdGVyaWFsLXRhYmxlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1hZHZhbmNlZC1tYXRlcmlhbC10YWJsZS9zcmMvbGliL25neC1hZHZhbmNlZC1tYXRlcmlhbC10YWJsZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtYWR2YW5jZWQtbWF0ZXJpYWwtdGFibGUvc3JjL2xpYi9uZ3gtYWR2YW5jZWQtbWF0ZXJpYWwtdGFibGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUM7QUFDNUIsb0RBQW9EO0FBQ3BELGdDQUFnQztBQUNoQyxPQUFPLEVBQUUsU0FBUyxFQUFVLEtBQUssRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBb0MsTUFBTSxlQUFlLENBQUM7QUFDNUgsT0FBTyxFQUFpRCxPQUFPLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVoRyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEMsT0FBTyxFQUVILFVBQVUsR0FLYixNQUFNLDBDQUEwQyxDQUFDO0FBQ2xELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUc3RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFMUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHNEQUFzRCxDQUFDO0FBQzlGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7OztBQU94RCxNQUFNLE9BQU8sOEJBQThCO0lBb0R2QyxZQUFvQixNQUFpQixFQUFVLG1CQUF3QyxFQUFVLEtBQXdCO1FBQXJHLFdBQU0sR0FBTixNQUFNLENBQVc7UUFBVSx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQXFCO1FBQVUsVUFBSyxHQUFMLEtBQUssQ0FBbUI7UUFwQi9HLG1CQUFjLEdBQThCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDL0QsZ0JBQVcsR0FBeUMsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN2RSxnQkFBVyxHQUFpQyxJQUFJLFlBQVksRUFBa0IsQ0FBQztRQUMvRSxpQkFBWSxHQUFpRCxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2hGLHFCQUFnQixHQUF5QyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBTXRGLHFCQUFnQixHQUFhLEVBQUUsQ0FBQztRQUVoQyxvQkFBZSxHQUFZLEtBQUssQ0FBQztRQUNqQyxxQkFBZ0IsR0FBWSxLQUFLLENBQUM7UUFDbEMsZUFBVSxHQUFHLFVBQVUsQ0FBQztRQUN4QixjQUFTLEdBQUcsSUFBSSxjQUFjLENBQUksSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRXBDLG9CQUFlLEdBQXdCLEVBQUUsQ0FBQztRQUMxQyxlQUFVLEdBQUcsRUFBRSxDQUFDO1FBNkJ4QixlQUFVLEdBQUcsQ0FBQyxNQUF5QixFQUFFLE9BQVUsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZHLGVBQVUsR0FBRyxDQUFDLEdBQU0sRUFBRSxNQUF5QixFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFJLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztRQTRnQjVGLFlBQVk7UUFFWiw4Q0FBOEM7UUFFOUMsc0JBQWlCLEdBQUcsWUFBWSxDQUFDLGlCQUFpQixDQUFDO1FBQ25ELHNCQUFpQixHQUFHLFlBQVksQ0FBQyxpQkFBaUIsQ0FBQztRQUNuRCxxQkFBZ0IsR0FBRyxZQUFZLENBQUMsZ0JBQWdCLENBQUM7UUFDakQsd0JBQW1CLEdBQUcsWUFBWSxDQUFDLG1CQUFtQixDQUFDO1FBQ3ZELCtCQUEwQixHQUFHLFlBQVksQ0FBQywwQkFBMEIsQ0FBQztRQUNyRSwrQkFBMEIsR0FBRyxZQUFZLENBQUMsMEJBQTBCLENBQUM7UUFDckUsb0JBQWUsR0FBRyxZQUFZLENBQUMsZUFBZSxDQUFDO0lBbGpCNkUsQ0FBQztJQTdDN0gsSUFDSSxZQUFZLENBQUMsS0FBMEI7UUFDdkMsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFDRCxJQUFJLFlBQVk7UUFDWixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7SUFDaEMsQ0FBQztJQUdELElBQWEsSUFBSSxDQUFDLEtBQVU7UUFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFDRCxJQUFJLElBQUk7UUFDSixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVELElBQWEsWUFBWSxDQUFDLGdCQUFxQjtRQUMzQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksY0FBYyxDQUFNLElBQUksRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7SUFFRCxJQUFJLFlBQVk7UUFDWixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDO0lBQ25DLENBQUM7SUF3QkQsUUFBUTtRQUNKLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUVELGVBQWU7UUFDWCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsR0FBUyxFQUFFLEVBQUU7WUFDekMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUU7Z0JBQ2IsT0FBTzthQUNWO1lBRUQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtnQkFDcEMsSUFBSSxNQUFNLENBQUMsS0FBSyxLQUFLLEdBQUcsQ0FBQyxNQUFNLEVBQUU7b0JBQzdCLE1BQU0sQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO2lCQUNwQztxQkFBTTtvQkFDSCxNQUFNLENBQUMsYUFBYSxHQUFHLEdBQUcsQ0FBQyxTQUF1QyxDQUFDO2lCQUN0RTtZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUtPLGVBQWU7UUFDbkIsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ1gsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7U0FDakQ7UUFFRCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksa0JBQWtCLENBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZELElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDM0MsSUFBSSxDQUFDLFVBQVUsQ0FBQyxtQkFBbUIsR0FBRyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBRTtZQUNyRCxNQUFNLE9BQU8sR0FBRyxZQUFZLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUV4RCxJQUFJLENBQUMsT0FBTyxFQUFFO2dCQUNWLE9BQU8sRUFBRSxDQUFDO2FBQ2I7WUFFRCxPQUFPLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM1QyxDQUFDLENBQUM7UUFDRixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBRWpDLElBQUksQ0FBQyxVQUFVLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzVELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRU8sYUFBYTtRQUNqQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEtBQUssSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEgsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsV0FBVyxFQUFFO1lBQ3JDLHVDQUF1QztZQUN2QyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQzNDO0lBQ0wsQ0FBQztJQUVELFlBQVksQ0FBQyxHQUFNO1FBQ2YsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsY0FBYyxFQUFFO1lBQ3hDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUNsQzthQUFNO1lBQ0gsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ2hDO1FBRUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRCxhQUFhLENBQUMsR0FBTTtRQUNoQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRUQsWUFBWTtRQUNSLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRWxILElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQsYUFBYTtRQUNULE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztRQUNuRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDNUMsT0FBTyxXQUFXLEtBQUssT0FBTyxDQUFDO0lBQ25DLENBQUM7SUFFRCxrQkFBa0I7UUFDZCxPQUFPLENBQUMsR0FBTSxFQUFFLE9BQWUsRUFBVyxFQUFFO1lBQ3hDLE1BQU0sVUFBVSxHQUF1QixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzNELEtBQUssTUFBTSxNQUFNLElBQUksVUFBVSxFQUFFO2dCQUM3QixJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtvQkFDNUIsU0FBUztpQkFDWjtnQkFFRCxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ25DLElBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxLQUFLLEVBQUUsRUFBRTtvQkFDeEIsT0FBTyxLQUFLLENBQUM7aUJBQ2hCO2dCQUVELElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNmLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsUUFBUSxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssVUFBVSxDQUFDLElBQUksRUFBRTtvQkFDeEUsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3BELEtBQUssR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLEtBQUssS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7aUJBQ25FO3FCQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDN0IsS0FBSyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO29CQUMzQixLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQy9EO3FCQUFNO29CQUNILEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDL0Q7Z0JBRUQsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLEVBQUU7b0JBQ2QsT0FBTyxLQUFLLENBQUM7aUJBQ2hCO2FBQ0o7WUFFRCxJQUFJLElBQUksQ0FBQyxVQUFVLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUMvQyxJQUFJLEtBQUssR0FBRyxLQUFLLENBQUM7Z0JBRWxCLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtvQkFDMUIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNyQyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7b0JBQ3hDLEtBQUssR0FBRyxLQUFLLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQ2pFLENBQUMsQ0FBQyxDQUFDO2dCQUNILE9BQU8sS0FBSyxDQUFDO2FBQ2hCO1lBRUQsT0FBTyxJQUFJLENBQUM7UUFDaEIsQ0FBQyxDQUFDO0lBQ04sQ0FBQztJQUVELGNBQWMsQ0FBQyxLQUFhLEVBQUUsS0FBVTtRQUNwQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRTtZQUM1RixLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdkIsT0FBTztTQUNWO1FBRUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUNyRSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVELGVBQWU7UUFDWCxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQXlCLEVBQUUsRUFBRTtZQUN2RCxNQUFNLENBQUMsYUFBYSxHQUFHLFNBQVMsQ0FBQztZQUNqQyxNQUFNLENBQUMsWUFBWSxHQUFHLFNBQVMsQ0FBQztRQUNwQyxDQUFDLENBQUMsQ0FBQztRQUVILHFFQUFxRTtRQUNyRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFFakIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxnQkFBZ0IsQ0FBQyxNQUFtQjtRQUNoQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0F