@circe/table
Version:
Circe Components for Angular :: Table Component
797 lines (792 loc) • 65.2 kB
JavaScript
import { Injectable, EventEmitter, Component, ChangeDetectionStrategy, Renderer2, ViewChild, ViewChildren, Input, Output, HostListener, ElementRef, ChangeDetectorRef, NgModule } from '@angular/core';
import { ToolService, IconsOld, EventsService, BoxModelService, BoxModelModule, EventsModule, ToolModule } from '@circe/core';
import { BehaviorSubject, Subject, isObservable, combineLatest, of, fromEvent } from 'rxjs';
import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
import { takeUntil, map, delay, tap, debounceTime } from 'rxjs/operators';
import { SelectComponent, SelectModule } from '@circe/select';
import { PaginationComponent } from '@circe/pagination';
import { CommonModule } from '@angular/common';
import { BadgeModule } from '@circe/badge';
import { FormsModule } from '@angular/forms';
import { FormBehaviorModule } from '@circe/form-behavior';
import { DropdownModule } from '@circe/dropdown';
import { KeyboardEmitterModule } from '@circe/event-controls';
import { SpinnerModule } from '@circe/spinner';
import { TooltipModule } from '@circe/tooltip';
class TableService {
constructor() {
this.tables = {};
}
_checkExists(tableId, columnId, asArray = false) {
if (!this.tables[tableId]) {
this.tables[tableId] = {};
}
if (!this.tables[tableId][columnId]) {
this.tables[tableId][columnId] = asArray ? [] : {};
}
}
addCheckboxData(tableId, rowId, columnId) {
if (!this.tables[tableId]) {
this.tables[tableId] = {};
}
if (!this.tables[tableId][columnId]) {
this.tables[tableId][columnId] = [];
}
this.tables[tableId][columnId].push(rowId);
}
setRadioData(tableId, rowId, columnId) {
this._checkExists(tableId, columnId);
this.tables[tableId][columnId] = rowId;
}
setSelectData(tableId, rowId, columnId, value) {
this._checkExists(tableId, columnId);
if (!this.tables[tableId][columnId][rowId]) {
this.tables[tableId][columnId][rowId] = {};
}
this.tables[tableId][columnId][rowId] = value;
}
deleteCheckboxData(tableId, rowId, columnId) {
this._checkExists(tableId, columnId, true);
this.tables[tableId][columnId] = this.tables[tableId][columnId].filter((id) => id !== rowId);
}
getColumnData(tableId, columnId) {
const _table = this.tables[tableId];
return _table[columnId] ? _table[columnId] : {};
}
}
TableService.decorators = [
{ type: Injectable }
];
TableService.ctorParameters = () => [];
class TableSource {
constructor(data, _filter, _paginator, _sorter) {
this.totalItems$ = new BehaviorSubject(0);
this._data$ = new BehaviorSubject([]);
this._filter$ = new BehaviorSubject([]);
this._sorter$ = new BehaviorSubject(null);
this._paginator$ = new BehaviorSubject(null);
this._renderChanges$ = new BehaviorSubject([]);
this.cancelStream$ = new Subject();
if (data) {
this.data = data;
}
if (_filter) {
this.filter = _filter;
}
if (_sorter) {
this.sorter = _sorter;
}
if (_paginator) {
this.paginator = _paginator;
}
this._getDataObservable();
}
get data() {
return this._data$;
}
set data(data) {
var _a;
if (data) {
if (isObservable(data)) {
(_a = this._dataSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
this._dataSubscription = data.subscribe((data) => this._data$.next(data));
}
else {
this._data$.next(data);
}
}
}
get filter() {
return this._filter$;
}
set filter(filter) {
var _a;
if (filter) {
if (isObservable(filter)) {
(_a = this._filterSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
this._filterSubscription = filter.subscribe((filter) => this._filter$.next(filter));
}
else {
this._filter$.next(filter);
}
}
}
get sorter() {
return this._sorter$;
}
set sorter(sorter) {
var _a;
if (sorter) {
if (isObservable(sorter)) {
(_a = this._sortSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
this._sortSubscription = sorter.subscribe((sort) => this._sorter$.next(sort));
}
else {
this._sorter$.next(sorter);
}
}
}
get paginator() {
return this._paginator$;
}
set paginator(paginator) {
var _a;
if (paginator) {
if (isObservable(paginator)) {
(_a = this._pageSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
this._pageSubscription = paginator.subscribe((page) => this._paginator$.next(page));
}
else {
this._paginator$.next(paginator);
}
}
}
static sortRows(rows, columnId, order = 'asc') {
const _output = rows.map((e) => {
return (e[columnId] === undefined) ? Object.assign(Object.assign({}, e), { [columnId]: '' }) : (e[columnId] === 0) ? Object.assign(Object.assign({}, e), { [columnId]: '0' }) : e;
}).sort((a, b) => (order === 'asc') ? (a[columnId] > b[columnId] ? 1 : -1) : (a[columnId] < b[columnId] ? 1 : -1));
return _output;
}
static filterRows(rows, filters) {
const _output = rows
.filter((row) => {
const _filterSuccess = filters.filter((f) => !!f.columns && !!f.value).every((f) => {
return f.columns.some((columnId) => {
const _value = ToolService.getValueFromMultiLevelObject(row, String(columnId)).toString().toLowerCase();
const _filterValue = f.value.toString().toLowerCase();
return f.searchExactly ? _value === _filterValue : _value.includes(_filterValue);
});
});
return _filterSuccess;
});
return _output;
}
_getDataObservable() {
var _a;
let _dataStream = isObservable(this._data$) ?
this._data$ : new BehaviorSubject(this._data$);
let _filterStream = isObservable(this._filter$) ?
this._filter$ : new BehaviorSubject(this._filter$);
let _sortStream = isObservable(this._sorter$) ?
this._sorter$ : new BehaviorSubject(this._sorter$);
let _pageStream = isObservable(this._paginator$) ?
this._paginator$ : new BehaviorSubject(this._paginator$);
this.cancelStream$.next();
_dataStream = _dataStream.pipe(takeUntil(this.cancelStream$));
_filterStream = _filterStream.pipe(takeUntil(this.cancelStream$));
_sortStream = _sortStream.pipe(takeUntil(this.cancelStream$));
_pageStream = _pageStream.pipe(takeUntil(this.cancelStream$));
const _filteredData = combineLatest([_dataStream, _filterStream])
.pipe(map(([data, filters]) => {
return this._filterRows(data, filters);
}));
const _orderedData = combineLatest([_filteredData, _sortStream])
.pipe(map(([data, sort]) => {
return this._orderRows(data, sort);
}));
const _paginatedData = combineLatest([_orderedData, _pageStream])
.pipe(map(([data, page]) => {
return this._pageRows(data, page);
}));
(_a = this._renderChangesSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
this._renderChangesSubscription = _paginatedData.subscribe((d) => {
this._renderChanges$.next(d);
});
}
_filterRows(data, filters) {
if (!(filters === null || filters === void 0 ? void 0 : filters.length)) {
this.totalItems$.next(data.length);
return data;
}
const _filteredData = TableSource.filterRows(data, filters);
const _actualPage = isObservable(this._paginator$) ? this._paginator$.value : this._paginator$;
const _newPage = { pageFirstItem: 0, itemsPerPage: _actualPage === null || _actualPage === void 0 ? void 0 : _actualPage.itemsPerPage };
if (this._paginator$) {
this._paginator$.next(_newPage);
this.totalItems$.next(_filteredData.length);
}
return _filteredData;
}
_orderRows(data, sort) {
if (!sort || !sort.columnId || !sort.sortType) {
return data;
}
return [...TableSource.sortRows(data.slice(), sort.columnId, sort.sortType)];
}
_pageRows(data, page) {
if (!!page && !!page.itemsPerPage && page.pageFirstItem >= 0) {
const startIndex = page.pageFirstItem;
return data.slice(startIndex, startIndex + (page.itemsPerPage));
}
return data;
}
_isPaginationComponent(obj) {
return !!obj && (obj instanceof PaginationComponent || (typeof obj.ngOnInit === 'function' && typeof obj.ngOnChanges === 'function'));
}
connect() {
return this._renderChanges$;
}
}
function _isTableSource(obj) {
return !!obj && (obj instanceof TableSource || (typeof obj.connect === 'function'));
}
class NpaTableConfiguration {
constructor(rows$, configModel) {
this.tableHeight$ = new BehaviorSubject('');
this._defaultConfiguration = {
keyColumnParam: 'id',
defaultActionColumnId: 'id',
columns: [],
minColumnWidth: 50,
showHeader: true,
sortTable: true,
hoverRows: false,
truncateTexts: false,
emitOnScroll: false
};
this._rows$ = rows$;
this._processConfiguration(typeof configModel === 'object' ? Object.assign(Object.assign({}, this._defaultConfiguration), configModel) : this._defaultConfiguration);
}
_processConfiguration(config) {
if ('keyColumnParam' in config) {
this.keyColumnParam = config.keyColumnParam;
}
else {
throw new Error('You must provide keyColumnParam config in order to get the id from every row.');
}
if ('defaultActionColumnId' in config) {
this.defaultActionColumnId = config.defaultActionColumnId;
}
if ('showHeader' in config) {
this.showHeader = config.showHeader;
}
if ('sortTable' in config) {
this.sortTable = config.sortTable;
}
if ('hoverRows' in config) {
this.hoverRows = config.hoverRows;
}
if ('tableHeight' in config) {
this.tableHeight$.next(config.tableHeight + 'px');
}
if ('minColumnWidth' in config) {
this.minColumnWidth = config.minColumnWidth;
}
if ('truncateTexts' in config) {
this.truncateTexts = config.truncateTexts;
}
if ('actionsConfig' in config) {
this.actionsConfigurationModel = config.actionsConfig;
}
if ('emitOnScroll' in config) {
this.emitOnScroll = config.emitOnScroll;
}
if ('columns' in config) {
this.columns = this._processColumnsConfig(config.columns);
}
const _columnsLength = this.columns.length;
this.minRowWidth = (this.minColumnWidth * _columnsLength) + 24 * _columnsLength;
}
_processColumnsConfig(columns) {
const _auxColumns = [];
for (const column of columns) {
_auxColumns.push(Object.assign(Object.assign({}, column), { sortable: 'sortable' in column ? column.sortable : true }));
// this.checkboxColumnsModel[column.id] = {
// checkAll: false,
// checkNone: true,
// model: false
// };
}
const _columnsWidths = _auxColumns.map((c) => c.columnWidth);
this._calculateColumnsWidth(_columnsWidths);
// for (const _column of _auxColumns) {
// if (_column.type === 'checkbox') {
// const _checkboxColumnsModel: NpaTableCheckboxSelection = this.checkboxColumnsModel[_column.id];
// this.checkColumnCheckboxes(_column.id);
// _checkboxColumnsModel.model = _checkboxColumnsModel.checkAll || !_checkboxColumnsModel.checkNone;
// }
// }
return _auxColumns;
}
_calculateColumnsWidth(columnsWidths) {
const _showActionsColumn = this.actionsConfigurationModel && !this.actionsConfigurationModel.hideColumn;
const _columnsWidths = _showActionsColumn ?
[...columnsWidths, this.actionsConfigurationModel.columnWidth] : columnsWidths;
const totalPercentage = 100;
let gridColumnsWidth = [];
let auxPercentage = totalPercentage;
let columnWidthsCount = 0;
let columnsWithoutWidthCount = 0;
for (const _columnWidth of _columnsWidths) {
if (_columnWidth && (auxPercentage - _columnWidth) >= 0) {
auxPercentage -= _columnWidth;
columnWidthsCount++;
}
else {
columnsWithoutWidthCount++;
}
}
if (auxPercentage === totalPercentage) {
gridColumnsWidth = new Array(_columnsWidths.length).fill(`${totalPercentage / _columnsWidths.length}%`, 0, _columnsWidths.length);
}
else if (auxPercentage >= 0) {
gridColumnsWidth = _columnsWidths.map((columnWidth) => `${columnWidth !== null && columnWidth !== void 0 ? columnWidth : (auxPercentage / columnsWithoutWidthCount)}%`);
}
if (this.minColumnWidth) {
gridColumnsWidth = gridColumnsWidth.map((width, i) => {
const _minWidth = _showActionsColumn && i === gridColumnsWidth.length - 1 ? 16 : this.minColumnWidth;
return `minmax(${_minWidth}px, ${width})`;
});
}
this.columnsWidth = gridColumnsWidth.join(' ');
}
}
class NpaTableActionsConfiguration {
constructor(configModel) {
this._defaultConfiguration = {
dropdownConfig: {
elementReference: ''
},
actionsType: 'link',
columnWidth: 5,
showOnHover: false,
group: true,
hideColumn: false,
defaultActionId: ''
};
this._processConfiguration(typeof configModel === 'object' ? Object.assign(Object.assign({}, this._defaultConfiguration), configModel) : this._defaultConfiguration);
}
_processConfiguration(config) {
var _a;
if ('dropdownConfig' in config) {
this.dropdownConfig = Object.assign(Object.assign({}, this.dropdownConfig), config.dropdownConfig);
}
if ('actionsType' in config) {
this.actionsType = config.actionsType;
}
if ('columnWidth' in config) {
this.columnWidth = config.columnWidth;
}
if ('group' in config) {
this.group = config.group;
}
if ('hideColumn' in config) {
this.hideColumn = config.hideColumn;
}
if ('showOnHover' in config) {
this.showOnHover = config.showOnHover;
}
if ('actions' in config) {
this.actions = config.actions;
}
if ('defaultActionId' in config) {
this.defaultActionId = config.defaultActionId;
}
if (this.group && !((_a = this.dropdownConfig) === null || _a === void 0 ? void 0 : _a.elementRelative)) {
throw new Error('If actions are grouped, an elementRelative for dropdown config is required.');
}
if (config.actions && !this.group && !this.actionsType) {
throw new Error('You must provide a type for actions.');
}
}
}
class TableComponent {
constructor(ev, tools, tableService, _renderer) {
this.ev = ev;
this.tools = tools;
this.tableService = tableService;
this._renderer = _renderer;
this.internalUpdate = new EventEmitter();
this.sortChange = new EventEmitter();
this.scrolledToBottom = new EventEmitter();
this.internalId = ToolService.generateUuid();
this.rows$ = new BehaviorSubject([]);
this.checkboxColumnsModel = {};
this.rowsHoverState = [];
this.groupActions$ = new BehaviorSubject(false);
this.showInternalSpinner$ = new BehaviorSubject(false);
this.manualActionsHide$ = new Subject();
this.sort$ = new BehaviorSubject(null);
this._originalDataCopy = [];
this._componentDestroyed$ = new Subject();
this._iconHandler = new IconsOld();
}
get sort() {
return this.sort$.value;
}
set sort(sort) {
var _a;
(_a = this._sortSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
this._sortSubscription = isObservable(sort) ? sort.subscribe(this.sort$) : of(sort).subscribe(this.sort$);
}
onResize() {
this.showInternalSpinner$.next(true);
}
_setDataStream() {
var _a;
if (this.data) {
if (Array.isArray(this.data)) {
this.dataSource$ = of(this.data);
}
else if (isObservable(this.data)) {
this.dataSource$ = this.data;
}
else if (_isTableSource(this.data)) {
this.dataSource$ = this.data.connect();
}
else {
throw new Error('[TableComponent]: data input must be of type T[], Observable<T[]> or TableSource<T>');
}
(_a = this.dataSourceSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
this.dataSourceSubscription = this.dataSource$.pipe(takeUntil(this._componentDestroyed$)).subscribe((data) => {
var _a;
this._originalDataCopy = [...data];
this.rows$.next(this._processRows(data, (_a = this.tableConfiguration) === null || _a === void 0 ? void 0 : _a.columns));
});
this.rows$.pipe(takeUntil(this._componentDestroyed$), delay(1), tap((rows) => {
this._setScrollListener();
this._viewPort.checkViewportSize();
})).subscribe();
}
}
_processRows(rows, columnsConfig) {
return columnsConfig ? rows.map((row) => {
return columnsConfig.map((c) => this._processColumn(row, c));
}) : [];
}
_processColumn(rowData, columnConfig) {
const column = Object.assign({}, columnConfig);
let auxColumn = Object.assign({ sortable: true }, columnConfig);
switch (column.type) {
case 'checkbox':
auxColumn = this._processCheckboxColumn(column, rowData);
break;
case 'radio':
auxColumn = this._processRadioColumn(column);
break;
case 'select':
auxColumn = this._processSelectColumn(column, rowData);
break;
case 'icon':
auxColumn = this._processIconColumn(rowData, column);
break;
case 'badge':
auxColumn = this._processBadgeColumn(rowData, column);
break;
case 'date':
auxColumn = this._processDateColumn(rowData, column);
break;
default:
if ('param' in columnConfig) {
auxColumn.value = ToolService.getValueFromMultiLevelObject(rowData, columnConfig.param);
}
}
return auxColumn;
}
_processCheckboxColumn(columnConfig, rowData) {
const _rowId = ToolService.getValueFromMultiLevelObject(rowData, this.tableConfiguration.keyColumnParam);
const _checkboxColumn = Object.assign({}, columnConfig);
const _tableServiceData = this.tableService.tables[this.id];
const _columnConfigData = _tableServiceData ? _tableServiceData[columnConfig.id] : null;
_checkboxColumn.value = !!_columnConfigData && _columnConfigData.includes(_rowId);
return _checkboxColumn;
}
_processRadioColumn(columnConfig) {
const _radioColumn = Object.assign({}, columnConfig);
const _tableServiceData = this.tableService.tables[this.id];
const _columnConfigData = _tableServiceData ? _tableServiceData[columnConfig.id] : null;
_radioColumn.value = _columnConfigData !== null && _columnConfigData !== void 0 ? _columnConfigData : -1;
return _radioColumn;
}
_processSelectColumn(columnConfig, rowData) {
const _rowId = ToolService.getValueFromMultiLevelObject(rowData, this.tableConfiguration.keyColumnParam);
const _columnConfigIsSet = !!columnConfig.typeConfig;
const _selectColumn = Object.assign({}, columnConfig);
const _typeConfig = _selectColumn.typeConfig;
const _tableServiceData = this.tableService.tables[this.id];
const _columnConfigData = _tableServiceData ? _tableServiceData[columnConfig.id] : null;
_selectColumn.selectConfig = Object.assign(Object.assign({ dropdownRelativeElement: 'npa-table__viewport' }, _typeConfig.selectConfig), { size: 'small', setDropdownParentTo: { type: 'id', name: 'npa-table-' + this.internalId } });
if (_columnConfigIsSet) {
if ('defaultValue' in _typeConfig) {
_selectColumn.value = _typeConfig.defaultValue;
}
if ('multilevel' in _typeConfig) {
_selectColumn.selectConfig = Object.assign(Object.assign({}, _selectColumn.selectConfig), { multiple: _typeConfig.multilevel, multipleSelectionBehavior: 'checkbox' });
_selectColumn.value = _columnConfigData ? _columnConfigData[_rowId] : [];
}
else {
_selectColumn.value = _columnConfigData ? _columnConfigData[_rowId] : '';
}
if ('placeholder' in _typeConfig) {
_selectColumn.selectConfig = Object.assign(Object.assign({}, _selectColumn.selectConfig), { placeholder: _typeConfig.placeholder });
}
if (_selectColumn.selectConfig.multiple && 'multilevelButtonLabel' in _typeConfig) {
_selectColumn.selectConfig = Object.assign(Object.assign({}, _selectColumn.selectConfig), { confirmButtonLabel: _typeConfig.multilevelButtonLabel });
}
}
return _selectColumn;
}
_processIconColumn(rowData, columnConfig) {
const _columnConfigIsSet = !!columnConfig.typeConfig;
const _selectColumn = Object.assign({}, columnConfig);
const _typeConfig = _selectColumn.typeConfig;
if (_columnConfigIsSet) {
if ('icon' in _typeConfig) {
_selectColumn.icon = this._getIcon(rowData, columnConfig);
}
if ('onlyIcon' in _typeConfig) {
_selectColumn.onlyIcon = _typeConfig.onlyIcon;
}
if ('param' in columnConfig) {
_selectColumn.value = ToolService.getValueFromMultiLevelObject(rowData, columnConfig.param);
}
}
return _selectColumn;
}
_processBadgeColumn(rowData, columnConfig) {
const _columnConfigIsSet = !!columnConfig.typeConfig;
const _badgeColumn = Object.assign({}, columnConfig);
const _typeConfig = _badgeColumn.typeConfig;
if (_columnConfigIsSet) {
if ('type' in _typeConfig) {
_badgeColumn.badgeType = this._getBadgeType(rowData, columnConfig);
}
if ('param' in columnConfig) {
_badgeColumn.value = ToolService.getValueFromMultiLevelObject(rowData, columnConfig.param);
}
}
return _badgeColumn;
}
_processDateColumn(rowData, columnConfig) {
const _columnConfigIsSet = !!columnConfig.typeConfig;
const _dateColumn = Object.assign({}, columnConfig);
if (_columnConfigIsSet) {
if ('param' in columnConfig) {
_dateColumn.value = new Date(ToolService.getValueFromMultiLevelObject(rowData, columnConfig.param));
}
}
return _dateColumn;
}
_getBadgeType(row, column) {
const _typeConfig = column.typeConfig;
const _badgeType = _typeConfig.type;
if (_badgeType) {
return (typeof _badgeType === 'function' ? _badgeType(row) : _badgeType);
}
return '';
}
_getIcon(row, column) {
let auxIcon = { classes: '' };
const _typeConfig = column.typeConfig;
const _icon = _typeConfig.icon;
if (_icon) {
auxIcon = (typeof _icon === 'function' ? _icon(row) : _icon);
}
return this._iconHandler.getIcon(auxIcon);
}
_getTableValue() {
return this.rows$.value.map(this.getRowValue.bind(this));
}
_hideAllDropdowns() {
this.manualActionsHide$.next();
if (this.selects.length) {
for (const _select of this.selects) {
if (_select.showDropdown) {
_select.setDropdown();
}
}
}
}
_setScrollListener() {
var _a;
if (!!this._viewPort) {
(_a = this._scrollSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
this._scrollSubscription = fromEvent(this._viewPort.getElementRef().nativeElement, 'scroll')
.pipe(tap(() => this._hideAllDropdowns()), debounceTime(300), takeUntil(this._componentDestroyed$)).subscribe(this.checkScroll.bind(this));
}
}
_setResizeListener() {
fromEvent(window, 'resize')
.pipe(tap(() => this.manualActionsHide$.next()), debounceTime(300), takeUntil(this._componentDestroyed$))
.subscribe(() => {
this.showInternalSpinner$.next(false);
});
this.showInternalSpinner$.pipe(takeUntil(this._componentDestroyed$), delay(1))
.subscribe(() => {
if (this._viewPort) {
this._viewPort.checkViewportSize();
}
});
}
_processConfiguration(config) {
this.tableConfiguration = new NpaTableConfiguration(this.rows$, config);
this.tableActionsConfiguration = new NpaTableActionsConfiguration(this.tableConfiguration.actionsConfigurationModel);
this._checkBiggerTableActions(this.tableActionsConfiguration.group);
}
ngOnInit() {
this._processConfiguration(this.config);
this._setDataStream();
}
ngAfterViewInit() {
this._setResizeListener();
}
ngOnChanges(changes) {
var _a, _b, _c, _d;
if (this.hotRender && (((_a = changes.config) === null || _a === void 0 ? void 0 : _a.currentValue) && ((_b = changes.config) === null || _b === void 0 ? void 0 : _b.previousValue))) {
this._processConfiguration((_c = changes.config) === null || _c === void 0 ? void 0 : _c.currentValue);
this._setDataStream();
}
if ((_d = changes.data) === null || _d === void 0 ? void 0 : _d.currentValue) {
this._setDataStream();
this._checkBiggerTableActions(this.groupActions$.value);
}
}
checkColumnCheckboxes(columnId) {
const _rows = [...this.rows$.value];
const columnValues = _rows.map((r) => { var _a; return !!((_a = r.find((c) => c.id === columnId)) === null || _a === void 0 ? void 0 : _a.value); });
if (!this.checkboxColumnsModel[columnId]) {
this.checkboxColumnsModel[columnId] = {
checkAll: false,
checkNone: true,
model: false
};
}
this.checkboxColumnsModel[columnId].checkAll = !!_rows.length && columnValues && (columnValues === null || columnValues === void 0 ? void 0 : columnValues.every((v) => v));
this.checkboxColumnsModel[columnId].checkNone = columnValues === null || columnValues === void 0 ? void 0 : columnValues.every((v) => !v);
this.checkboxColumnsModel[columnId].model = this.checkboxColumnsModel[columnId].checkAll || !this.checkboxColumnsModel[columnId].checkNone;
}
sortTableRows(column) {
if (this.tableConfiguration.sortTable && column.sortable && column.columnName) {
const { sortType, columnId } = this.sort$.value;
const _newSortType = (sortType === 'desc' || columnId !== column.id) ? 'asc' : 'desc';
this.sort$.next({ columnId: column.id, sortType: _newSortType });
this.sortChange.emit({ columnId: column.id, sortType: _newSortType });
}
}
updateRadioColumn(columnId, newValue) {
const _rows = [...this.rows$.value];
_rows.forEach((row, rowIndex) => {
const _column = row.find((r) => r.id === columnId);
_column.value = newValue;
if (_column.rowId === newValue) {
const _row = this.getRowValue(row, rowIndex);
const _rowId = ToolService.getValueFromMultiLevelObject(_row.npaTableDataSource, this.tableConfiguration.keyColumnParam);
this.tableService
.setRadioData(this.id, _rowId, _column.id);
}
});
this.internalUpdate.emit(this._getTableValue());
}
updateCheckboxColumn(column, row, rowIndex, newValue, bypassCheck) {
column.value = newValue;
if (!this.checkboxColumnsModel[column.id]) {
this.checkboxColumnsModel[column.id] = {
checkAll: false,
checkNone: true,
model: false
};
}
const _rows = [...this.rows$.value];
const _row = this.getRowValue(row, rowIndex);
const _rowId = ToolService.getValueFromMultiLevelObject(_row.npaTableDataSource, this.tableConfiguration.keyColumnParam);
const columnValues = _rows.map((r) => !!r.find((c) => c.id === column.id).value);
this.checkboxColumnsModel[column.id].checkAll = columnValues.every((v) => v);
this.checkboxColumnsModel[column.id].checkNone = columnValues.every((v) => !v);
// this.checkboxColumnsModel[column.id].model = this.checkboxColumnsModel[column.id].checkAll || !this.checkboxColumnsModel[column.id].checkNone;
if (newValue) {
this.tableService.addCheckboxData(this.id, _rowId, column.id);
}
else {
this.tableService.deleteCheckboxData(this.id, _rowId, column.id);
}
if (!bypassCheck) {
this.checkColumnCheckboxes(column.id);
}
this.internalUpdate.emit(this._getTableValue());
}
updateColumnValue(column, row, rowIndex, newValue) {
const _row = this.getRowValue(row, rowIndex);
const _rowId = ToolService.getValueFromMultiLevelObject(_row.npaTableDataSource, this.tableConfiguration.keyColumnParam);
column.value = newValue;
this.tableService
.setSelectData(this.id, _rowId, column.id, newValue);
this.internalUpdate.emit(this._getTableValue());
}
linkAction(column, row, rowIndex) {
const _typeConfig = column.typeConfig;
if (_typeConfig === null || _typeConfig === void 0 ? void 0 : _typeConfig.linkAction) {
_typeConfig.linkAction(this.getRowValue(row, rowIndex));
}
}
setColumnCheckboxes(columnId) {
const _rows = [...this.rows$.value];
this.checkboxColumnsModel[columnId].model = !this.checkboxColumnsModel[columnId].model;
_rows.forEach((row, rowIndex) => {
const _column = row.find((c) => c.id === columnId);
this.updateCheckboxColumn(_column, row, rowIndex, this.checkboxColumnsModel[columnId].model, true);
});
this.checkColumnCheckboxes(columnId);
this.internalUpdate.emit(this._getTableValue());
}
rowHover(columnIndex) {
this.rowsHoverState = new Array(this.rowsHoverState.length).fill(false);
this.rowsHoverState[columnIndex] = true;
}
tableMouseLeave() {
this.rowsHoverState = new Array(this.rowsHoverState.length).fill(false);
}
rowMouseLeave(rowIndex) {
this.rowsHoverState = [...this.rowsHoverState.slice(0, rowIndex), false, ...this.rowsHoverState.slice(rowIndex + 1)];
}
checkScroll() {
const _viewPortElement = this._viewPort.getElementRef().nativeElement;
const _bodyHasScroll = _viewPortElement.offsetHeight < _viewPortElement.scrollHeight;
if (this._viewPort && this.tableConfiguration.emitOnScroll) {
const _viewPort = this._viewPort.getElementRef().nativeElement;
if (_bodyHasScroll && _viewPort.scrollTop + _viewPort.offsetHeight >= _viewPort.scrollHeight) {
this.scrolledToBottom.emit();
}
}
}
getRowValue(row, rowIndex) {
var _a;
const _originalRow = (_a = this._originalDataCopy[rowIndex]) !== null && _a !== void 0 ? _a : {};
const _rowValue = {
npaTableDataSource: Object.assign({}, _originalRow)
};
for (const column of row) {
if (column.id !== 'npa-table-actions-column') {
_rowValue[column.id] = column.type === 'radio' ? (column.value === rowIndex) : column.value;
}
}
return Object.assign({}, _rowValue);
}
_checkBiggerTableActions(group) {
var _a, _b, _c;
let _biggerTableActions;
const _tableActionsComponents = this.tableActions ? Array.from(this.tableActions) : [];
for (const _tableActionsComponent of _tableActionsComponents) {
if (!_biggerTableActions || ((_a = _tableActionsComponent.actionsContainer) === null || _a === void 0 ? void 0 : _a.nativeElement.scrollWidth) > _biggerTableActions.scrollWidth) {
_biggerTableActions = (_b = _tableActionsComponent.actionsContainer) === null || _b === void 0 ? void 0 : _b.nativeElement;
}
}
const _tableActionsComponentParent = (_c = _tableActionsComponents[0]) === null || _c === void 0 ? void 0 : _c.el.nativeElement.parentNode;
if (!group && _biggerTableActions && _biggerTableActions.scrollWidth >= (_tableActionsComponentParent === null || _tableActionsComponentParent === void 0 ? void 0 : _tableActionsComponentParent.offsetWidth)) {
this.groupActions$.next(true);
}
else {
this.groupActions$.next(group);
}
}
ngOnDestroy() {
this._componentDestroyed$.next();
this._componentDestroyed$.complete();
this._componentDestroyed$.unsubscribe();
}
}
TableComponent.decorators = [
{ type: Component, args: [{
selector: 'npa-table',
template: "<div class=\"npa-table\" #table [id]=\"'npa-table-' + internalId\" [style.height]=\"tableConfiguration?.tableHeight$ | async\">\n <div\n class=\"npa-table__header\"\n #tableHeader\n *ngIf=\"tableConfiguration?.showHeader\"\n [ngStyle]=\"{ 'min-width': table?.offsetWidth < tableConfiguration.minRowWidth ? tableConfiguration.minRowWidth + 'px' : 'unset'}\"\n [style]=\"{'grid-template-columns': tableConfiguration.columnsWidth}\">\n <div\n class=\"npa-table__header-cell npa-table__header-cell--checkbox\"\n *ngFor=\"let column of tableConfiguration.columns; trackBy: tools.identifier;\"\n [ngClass]=\"{'sort': tableConfiguration.sortTable && column.sortable && column.columnName}\">\n <ng-container *ngIf=\"column.type === 'checkbox' && column.typeConfig.checkboxInHeader\">\n <input\n class=\"npa-selection--vertical\"\n type=\"checkbox\"\n [id]=\"column.id + '-check-all'\"\n [name]=\"column.id + '-check-all'\"\n [ngClass]=\"{\n 'npa-checkbox--indeterminate': (!checkboxColumnsModel[column.id]?.checkAll) && !checkboxColumnsModel[column.id]?.checkNone\n }\"\n [checked]=\"(checkboxColumnsModel[column.id]?.checkAll && !checkboxColumnsModel[column.id]?.checkNone) || checkboxColumnsModel[column.id]?.model\"\n [ngModel]=\"checkboxColumnsModel[column.id]?.model\"\n (ngModelChange)=\"setColumnCheckboxes(column.id)\">\n <label [for]=\"column.id + '-check-all'\"></label>\n </ng-container>\n <span\n class=\"npa-tooltip\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [showWhenTruncated]=\"true\"\n [title]=\"column.columnName\"\n (click)=\"sortTableRows(column)\">\n {{column.columnName}}\n </span>\n <i\n class=\"npa-icon\"\n *ngIf=\"tableConfiguration.sortTable && column.sortable && sort$.value?.sortType && sort$.value?.columnId === column.id\"\n [ngClass]=\"sort$.value.sortType === 'asc' ? 'icon-arrow-up' : 'icon-arrow-down'\"\n (click)=\"sortTableRows(column)\">\n </i>\n </div>\n <div class=\"npa-table__header-cell npa-table__header-cell--checkbox\" *ngIf=\"tableActionsConfiguration && !tableActionsConfiguration.hideColumn\"></div>\n </div>\n <div class=\"npa-table__body--overlay\" *ngIf=\"showSpinner || (showInternalSpinner$ | async)\">\n <div class=\"npa-table__spinner-container\">\n <npa-spinner></npa-spinner>\n </div>\n </div>\n <div\n class=\"npa-table__body\"\n #tableBody\n [ngClass]=\"{'hide': showSpinner || (showInternalSpinner$ | async)}\"\n (mouseleave)=\"tableMouseLeave()\">\n <cdk-virtual-scroll-viewport\n class=\"npa-table__viewport\"\n [ngStyle]=\"{ 'min-width': (table?.offsetWidth < tableConfiguration.minRowWidth) ? tableConfiguration.minRowWidth + 'px' : 'unset'}\"\n [ngClass]=\"{'hide': (rows$ | async)?.length < 1}\"\n [itemSize]=\"41\">\n <div\n class=\"npa-table__row\"\n #tableRow\n *cdkVirtualFor=\"let row of (rows$ | async); trackBy: tools.identifier; let rowIndex = index\"\n [ngClass]=\"{'hover': tableConfiguration.hoverRows}\"\n [style]=\"{'grid-template-columns': tableConfiguration.columnsWidth}\"\n (mouseenter)=\"rowHover(rowIndex)\"\n (mouseleave)=\"rowMouseLeave(rowIndex)\">\n <div\n class=\"npa-table__cell\"\n *ngFor=\"let column of row; trackBy: tools.identifier;\" [id]=\"column.id\">\n <ng-container *ngIf=\"!column.type\">\n <span\n class=\"npa-table__cell-value npa-tooltip npa-tooltip--small npa-tooltip--light\"\n *ngIf=\"(!rowsHoverState[rowIndex] || rowsHoverState && column.id !== tableConfiguration.defaultActionColumnId) || !defaultAction\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [showWhenTruncated]=\"true\"\n [title]=\"column.value\">\n <ng-container *ngIf=\"!!column.param && (!!column.value || column.value === 0)\">{{column.value}}</ng-container>\n <ng-container *ngIf=\"!!column.param && !column.value && column.value !== 0\">{{'-'}}</ng-container>\n </span>\n <a\n class=\"npa-table__cell-value npa-link npa-tooltip npa-tooltip--small npa-tooltip--light\"\n *ngIf=\"rowsHoverState[rowIndex] && column.id === tableConfiguration.defaultActionColumnId && defaultAction\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [title]=\"tableConfiguration.truncateTexts ? column.value : defaultAction.label\"\n [showWhenTruncated]=\"true\"\n (click)=\"defaultAction.callback(getRowValue(row, rowIndex))\">\n <ng-container *ngIf=\"!!column.param && (!!column.value || column.value === 0)\">{{column.value}}</ng-container>\n <ng-container *ngIf=\"!!column.param && !column.value && column.value !== 0\">{{'-'}}</ng-container>\n </a>\n </ng-container>\n <ng-container *ngIf=\"column.type === 'date'\">\n <span\n class=\"npa-table__cell-value npa-tooltip npa-tooltip--small npa-tooltip--light\"\n *ngIf=\"(!rowsHoverState[rowIndex] || rowsHoverState && column.id !== tableConfiguration.defaultActionColumnId) || !defaultAction\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [showWhenTruncated]=\"true\"\n [title]=\"column.value | date:(column.typeConfig?.dateMask || 'MM/dd/yyyy')\">\n {{column.value ? (column.value | date:(column.typeConfig?.dateMask || 'MM/dd/yyyy')) : '-'}}\n </span>\n <a\n class=\"npa-table__cell-value npa-link npa-tooltip npa-tooltip--small npa-tooltip--light\"\n *ngIf=\"rowsHoverState[rowIndex] && column.id === tableConfiguration.defaultActionColumnId && defaultAction\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [title]=\"tableConfiguration.truncateTexts ? (column.value | date:'MM/dd/yyyy') : defaultAction.label\"\n [showWhenTruncated]=\"true\"\n (click)=\"defaultAction.callback(getRowValue(row, rowIndex))\">\n {{column.value ? (column.value | date:'MM/dd/yyyy') : '-'}}\n </a>\n </ng-container>\n <ng-container *ngIf=\"column.type === 'checkbox'\">\n <input\n class=\"npa-selection--vertical npa-selection--no-label\"\n type=\"checkbox\"\n [id]=\"column.id + '-' + rowIndex\"\n [name]=\"column.id + '-' + rowIndex\"\n [ngModel]=\"column.value || checkboxColumnsModel[column.id]?.checkAll\"\n (ngModelChange)=\"updateCheckboxColumn(column, row, rowIndex, $event)\">\n <label [for]=\"column.id + '-' + rowIndex\">{{column.typeConfig?.label}}</label>\n </ng-container>\n <ng-container *ngIf=\"column.type === 'radio'\">\n <input\n type=\"radio\"\n class=\"npa-selection--no-label\"\n [attr.id]=\"column.id + '-' + rowIndex\"\n [name]=\"column.id\"\n [value]=\"column.rowId\"\n [ngModel]=\"column.value\"\n (ngModelChange)=\"updateRadioColumn(column.id, column.rowId)\">\n <label [attr.for]=\"column.id + '-' + rowIndex\">{{column.typeConfig?.label}}</label>\n </ng-container>\n <ng-container *ngIf=\"column.type === 'icon'\">\n <span\n class=\"npa-table__cell-value npa-tooltip npa-tooltip--small npa-tooltip--light\"\n *ngIf=\"!column.onlyIcon && ((!rowsHoverState[rowIndex] || rowsHoverState && column.id !== tableConfiguration.defaultActionColumnId) || !defaultAction)\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [showWhenTruncated]=\"true\"\n [title]=\"column.value\">\n <i *ngIf=\"column.icon\" [ngClass]=\"column.icon\"></i>\n <ng-container *ngIf=\"column.param && column.value\">{{column.value}}</ng-container>\n <ng-container *ngIf=\"column.param && !column.value\">{{'-'}}</ng-container>\n </span>\n <a\n class=\"npa-table__cell-value npa-link npa-tooltip npa-tooltip--small npa-tooltip--light\"\n *ngIf=\"rowsHoverState[rowIndex] && column.id === tableConfiguration.defaultActionColumnId && defaultAction\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [title]=\"tableConfiguration.truncateTexts ? column.value : defaultAction.label\"\n [showWhenTruncated]=\"true\"\n (click)=\"defaultAction.callback(getRowValue(row, rowIndex))\">\n <i *ngIf=\"column.icon\" [ngClass]=\"column.icon\"></i>\n <ng-container *ngIf=\"column.param && column.value\">{{column.value}}</ng-container>\n <ng-container *ngIf=\"column.param && !column.value\">{{'-'}}</ng-container>\n </a>\n </ng-container>\n <ng-container *ngIf=\"column.type === 'badge'\">\n <div class=\"npa-badge npa-badge--alone npa-badge--x-small\" [ngClass]=\"'npa-badge--' + column.badgeType\">\n <div class=\"npa-badge__box\"></div>\n </div>\n <span\n class=\"npa-table__cell-value npa-tooltip npa-tooltip--small npa-tooltip--light npa-color--critical\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [showWhenTruncated]=\"true\"\n [title]=\"column.value\">\n <ng-container *ngIf=\"column.param && column.value\">{{column.value}}</ng-container>\n <ng-container *ngIf=\"column.param && !column.value\">{{'-'}}</ng-container>\n </span>\n </ng-container>\n <ng-container *ngIf=\"column.type === 'link'\">\n <a\n class=\"npa-table__cell-value npa-link\"\n *ngIf=\"!!column.value\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n (click)=\"linkAction(column, row, rowIndex)\">\n {{column.typeConfig?.label ? column.typeConfig.label : column.value}}\n </a>\n <span\n class=\"npa-table__cell-value npa-tooltip npa-tooltip--small npa-tooltip--light npa-color--critical\"\n *ngIf=\"!column.value\"\n [ngClass]=\"{ 'truncate-text': tableConfiguration.truncateTexts }\"\n [showWhenTruncated]=\"true\"\n [title]=\"column.value\">-</span>\n </ng-container>\n <ng-container *ngIf=\"column.type === 'select'\">\n <label class=\"npa-label\" [for]=\"column.id + '-' + rowIndex\"></label>\n <npa-select\n [id]=\"column.id + '-' + rowIndex\"\n [config]=\"column.selectConfig\"\n [options]=\"column.typeConfig.options\"\n [ngModel]=\"column.value\"\n (ngModelChange)=\"updateColumnValue(column, row, rowIndex, $event)\">\n </npa-select>\n </ng-container>\n </div>\n <div\n class=\"npa-table__cell\" [class.hide]=\"tableActionsConfiguration.hideColumn\">\n <npa-table-actions\n #tableActions\n *ngIf=\"tableActionsConfiguration?.actions\"\n [class.hide]=\"tableActionsConfiguration.showOnHover && !rowsHoverState[rowIndex]\"\n [hotRender]=\"true\"\n [manualHideDropdown]=\"manualActionsHide$\"\n [isHoveringRow]=\"rowsHoverState[rowIndex]\"\n [tableRow]=\"row\"\n [rowData]=\"getRowValue(row, rowIndex)\"\n [group]=\"(groupActions$ | async)\"\n [actions]=\"tableActionsConfiguration.actions\"\n [setDropdownParentTo]=\"{ type: 'id', name: 'npa-table-' + internalId }\"\n [dropdownConfig]=\"tableActionsConfiguration.dropdownConfig\"\n [actionsType]=\"tableActionsConfiguration.actionsType\"\n [defaultActionId]=\"tableActionsConfiguration.defaultActionId\"\n (defaultAction)=\"defaultAction = $event\"\n (selectedOption)=\"$event.callback(getRowValue(row, rowIndex))\">\n </npa-table-actions>\n </div>\n </div>\n <div class=\"npa-table__row--spinner\" *ngIf=\"showLoadOnScrollSpinner\">\n <npa-spinner class=\"npa-spinner--20\"></npa-spinner>\n </div>\n </cdk-virtual-scroll-viewport>\n\n <div\n class=\"npa-table__body--overlay\"\n *ngIf=\"!((rows$ | async)?.length) && !showSpinner && (showInternalSpinner$ | async) === false\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n",
changeDetection: ChangeDetectionStrategy.OnPush,
styles: [":host{--npa-table-default-height:fit-content;--npa-table-default-column-gap:24px;--npa-table-default-column-padding:0 12px;--npa-table-header-default-height:40px;--npa-table-header-default-border-width:0 0 1px 0;--npa-table-header-default-border-style:solid;--npa-table-header-default-border-color:gray;--npa-table-header-cell-default-align:center;--npa-table-header-cell-default-justify:normal;--npa-table-header-cell-default-icon-size:12px;--npa-table-header-cell-default-icon-spacing:8px;--npa-table-header-cell-default-text-transform:uppercase;--npa-table-header-cell-default-color:gray;--npa-table-header-cell-default-icon-color:gray;--npa-table-body-default-height:calc(100% - var(--npa-table-header-default-height) - 1px);--npa-table-body-spinner-top-spacing:40px;--npa-table-row-default-height:40px;--npa-table-row-default-background-color:#fff;--npa-table-row-default-border-width:0 0 1px 0;--npa-table-row-default-border-style:solid;--npa-table-row-default-border-color:#d3d3d3;--npa-table-row-default-hover-background-color:#add8e6;--npa-table-row-default-hover-border-width:0 0 1px 0;--npa-table-row-default-hover-border-style:solid;--npa-table-row-default-hover-border-color:#d3d3d3;--npa-table-row-default-spinner-container-height:40px;--npa-table-row-default-spinner-padding:12px;--npa-table-row-cell-default-align:center;--npa-table-row-cell-default-justify:normal;--npa-table-row-cell-default-icon-spacing:8px;--npa-table-row-cell-default-color:#000}:host .npa-table{height:var(--npa-table-default-height);overflow-x:auto}:host .npa-table .npa-table__header{display:grid;grid-column-gap:var(--npa-table-default-column-gap);padding:var(--npa-table-default-column-padding);border:var(--npa-table-header-default-border-style) var