ngx-table-powerfull
Version:
Table with catalog of functionalities for free use based on the ngx-datatable component and other components
904 lines • 331 kB
JavaScript
import * as tslib_1 from "tslib";
import { Component, ViewChild, Input, Output, EventEmitter, HostListener, ViewEncapsulation } from '@angular/core';
import { fromEvent } from 'rxjs';
import { map, debounceTime } from 'rxjs/operators';
import { ColumnTableModel } from './models/columnTable.model';
import { NgxTableService } from './services/ngxTable.service';
import { NotificationNgxService } from './services/notificationNgx.service';
import { NgxTableDialogComponent } from './components/ngxTableDialog/ngxTableDialog.component';
import { MatDialog, MatDialogConfig } from '@angular/material';
import { NotificationTableModel } from './models/notificationTable.model';
import { EditColumnDialogComponent } from './components/editColumnDialog/editColumnDialog.component';
import { ActionColumnType } from './common/actionsColumn.type';
import { ConfigTableModel, ClassesAvailable } from './models/configTable.model';
import { SumaryTypes, FunctionTypes } from './models/sumaryColumn.model';
import { ExportsType } from './common/exports.type';
import { ActionsType } from './common/actions.type';
import { GridColumnsComponent } from './components/gridColumns/gridColumns.component';
import { StylesTypes, ThemeTypes } from './common/styles.types';
let NgxTableComponent = class NgxTableComponent {
constructor(ngxTableService, notification, dialog) {
this.ngxTableService = ngxTableService;
this.notification = notification;
this.dialog = dialog;
this.config = new ConfigTableModel();
this.viewDialog = false;
this.beforeAction = null;
this.actionsTocontrol = [];
this.event = new EventEmitter();
this.click = new EventEmitter();
this.dblclick = new EventEmitter();
this.singleSelection = new EventEmitter();
this.multipleSelection = new EventEmitter();
this.visibleDataTable = new EventEmitter();
this.dataTable = new EventEmitter();
this.updateRow = new EventEmitter();
this.newColumn = new EventEmitter();
this.editColumnOuput = new EventEmitter();
this.deleteColumnOuput = new EventEmitter();
this.editing = {};
this.alt = false;
this.asc = true;
this.columnsFilterList = [];
this.selectedColumnsFilter = [];
this.dropdownSettings = {};
this.selectColumnsFilter = false;
this.height = {};
this.indexNewColumn = 0;
this.sumaryColumns = [];
this.dataSumary = [];
this.getRowClass = (row) => {
return {
'row-active-add': this.rowsTempTableAdd.includes(row[this.indexColumn]) && !!this.config.multipleSelection,
'row-active': (this.backgroundActiveRow == row[this.indexColumn] && !!this.config.singleSelection) ? true : false
};
};
this.rowsTempTableAdd = [];
this.fullscreen = false;
this.temp = [];
this.rows = [];
this.indexColumn = '';
this.lastSortEvent = null;
}
ngOnInit() {
this.config = new ConfigTableModel(this.config);
if (!ClassesAvailable.includes(this.config.classTable))
this.config.classTable = ClassesAvailable[0];
this.setThemeStyles();
this.buildIndex();
this.checkPredefinedDataColumn();
this.searchActions();
this.getAll();
this.buildFilterByColumns();
this.dropdownSettings = {
singleSelection: false,
idField: 'item_id',
textField: 'item_text',
selectAllText: this.config.language.selectAll,
unSelectAllText: this.config.language.unSelectAll,
itemsShowLimit: 3,
allowSearchFilter: true,
searchPlaceholderText: this.config.language.search
};
this.primitiveHeight = (!!this.config.editableColumns) ? { fullscreen: 180, fullscreenFilter: 220 } : { fullscreen: 150, fullscreenFilter: 190 };
this.height = {
fullscreen: this.primitiveHeight.fullscreen,
fullscreenFilter: this.primitiveHeight.fullscreenFilter
};
this.sumaryColumns = this.columns.filter(c => !!new ColumnTableModel(c).sumary.length);
this.updateSumaryColumns();
}
ngAfterViewInit() {
if (!!this.config.filter) {
fromEvent(this.search.nativeElement, 'keydown')
.pipe(debounceTime(550), map(x => x['target']['value']))
.subscribe(value => {
this.updateFilter(value);
this.updateSumaryColumns();
});
}
this.columns.forEach(c => {
if (!!c.index)
this.indexColumn = c.prop;
});
this.resize(10);
}
ngAfterViewChecked() {
if (!!this.subscriptionChanges)
return;
this.subscriptionChanges = this.notification.on(this.name).subscribe(value => {
const data = new NotificationTableModel(value);
if (data.collapsed != null)
this.config.collapsed = data.collapsed;
if (!!data.rows.length) {
this.data = data.rows;
this.getAll();
if (!!this.config.filter && !!this.search.nativeElement.value)
this.updateFilter(this.search.nativeElement.value);
this.updateSumaryColumns();
}
if (!!data.columns.length) {
this.columns = data.columns;
this.buildFilterByColumns();
if (!!this.config.filter && !!this.search.nativeElement.value)
this.updateFilter(this.search.nativeElement.value);
this.updateSumaryColumns();
}
if (!!data.visibleDataTable) {
const columnsProp = (this.columns.filter(c => !c.hide && !c.action && !!c.visible)).map(c => c.prop);
this.visibleDataTable.emit({
name: ActionsType.VISIBLE_DATA_TABLE,
columns: this.columns.filter(c => !c.hide && !c.action && !!c.visible),
rows: this.rows.map(data => {
let obj = {};
Object.keys(data).forEach(k => {
if (!!columnsProp.includes(k)) {
Object.assign(obj, { [k]: data[k] });
}
});
return obj;
})
});
}
if (!!data.dataTable) {
const columnsProp = (this.columns.filter(c => !c.action)).map(c => c.prop);
this.dataTable.emit({
name: ActionsType.DATA_TABLE,
columns: this.columns.filter(c => !c.action),
rows: this.data.map(data => {
let obj = {};
Object.keys(data).forEach(k => {
if (!!columnsProp.includes(k)) {
Object.assign(obj, { [k]: data[k] });
}
});
return obj;
})
});
}
if (!!data.exportExcel)
this.export(ExportsType.EXCEL);
if (!!data.exportPdf)
this.export(ExportsType.PDF);
if (!!this.config.filter && !!this.search.nativeElement.value)
this.updateFilter(this.search.nativeElement.value);
this.resize(10);
});
}
/**
* onResize
*
* Calculates the height with the values indicated in the table configuration
*
*/
onResize(event) {
this.height = (event.target.innerWidth < 992)
? { fullscreen: this.primitiveHeight.fullscreen + 55, fullscreenFilter: this.primitiveHeight.fullscreenFilter + 54 }
: { fullscreen: this.primitiveHeight.fullscreen, fullscreenFilter: this.primitiveHeight.fullscreenFilter };
}
/**
* setThemeStyles
*
* Apply the styles indicated in the table config
*
*/
setThemeStyles() {
this.setPropertyCss({ key: StylesTypes.PRIMARY_COLOR, value: this.config.primaryColor }, { key: StylesTypes.HOVER_ROW_COLOR, value: this.config.hoverRowColor }, { key: StylesTypes.SECONDARY_COLOR, value: this.config.secondaryColor }, { key: StylesTypes.HEADER_BACKGROUND, value: this.config.headerBackground }, { key: StylesTypes.HEADER_FONT_COLOR, value: this.config.headerFontColor }, { key: StylesTypes.BORDER_TABLE_COLOR, value: this.config.borderTableColor });
if (!this.config.resizeColumns)
this.setPropertyCss({ key: StylesTypes.RESIZE_COLUMNS, value: 'none' });
if (this.config.classTable === ThemeTypes.MATERIAL) {
this.setPropertyCss({ key: StylesTypes.DROPDOWN_BORDER, value: 'transparent' }, { key: StylesTypes.DROPDOWN_BORDER_RADIUS, value: '0' }, { key: StylesTypes.DROPDOWN_BORDER_BOTTOM, value: 'grey' });
}
else
this.setPropertyCss({ key: StylesTypes.BOX_SHADOW_TABLE, value: 'none' });
}
/**
* setPropertyCss
*
* Notify css property
*
*/
setPropertyCss(...property) {
property.forEach(p => document.documentElement.style.setProperty(p.key, p.value));
}
/**
* buildIndex
*
* Look for the index column, in addition to discarding if there are more and if there is not, generate one automatically
*
*/
buildIndex() {
let foundIndex = null;
let indexColumn;
this.columns = this.columns.map((col, i) => {
if (foundIndex != null && !!col.index)
col.index = false;
if (!!col.index) {
foundIndex = i;
indexColumn = col;
}
return new ColumnTableModel(col);
});
if (foundIndex === null) {
const defaultProp = 'index_genrete_automatically_by_powerfull';
let index = {
prop: defaultProp,
name: 'Index',
index: true,
hide: true
};
this.columns.splice(0, 0, new ColumnTableModel(index));
this.data.forEach((data, i) => {
data[defaultProp] = i;
});
}
else {
if (foundIndex != 0) {
this.columns.splice(foundIndex, 1);
this.columns.splice(0, 0, new ColumnTableModel(indexColumn));
}
}
}
/**
* onChangeSelectFilter
*
* Update search filter when changing column selection
*
*/
onChangeSelectFilter() {
this.updateFilter(this.search.nativeElement.value);
this.updateSumaryColumns();
}
/**
* openConfigFilter
*
* Open config and close config filter table
*
*/
openConfigFilter() {
this.selectColumnsFilter = !this.selectColumnsFilter;
this.resize(10);
}
/**
* buildFilterByColumns
*
* Build the list of items to show in the filter by columns
*
*/
buildFilterByColumns() {
this.columnsFilterList = this.selectedColumnsFilter = this.columns.filter(col => !col.hide && !col.action && !!col.visible && !!col.filtered).map(col => Object.assign({ item_id: col.prop, item_text: col.name }));
}
/**
* searchActions
*
* Find columns with actions and build value and position finish
*
*/
searchActions() {
const columnsAction = this.columns.filter(c => !!c.action);
if (!!columnsAction.length) {
columnsAction.forEach(c => {
this.data.forEach(r => {
let value = `<${c.tag}`;
if (!!c.attributes.length) {
c.attributes.forEach(a => {
value += ` ${a.name}='${a.value}'`;
});
}
value += `>${r[c.prop]}</${c.tag}>`;
r[c.prop] = value;
});
});
}
this.columns = this.columns.filter(c => !c.action);
columnsAction.forEach(c => this.columns.push(c));
}
/**
* onActivate
*
* Capture and manage the different events on the table for row selection
*
* @param e $event
*/
onActivate(e) {
if (e.type == ActionsType.CLICK || e.type == ActionsType.DBL_CLICK) {
if (!e.event.shiftKey) {
(this.backgroundActiveRow != e.row[this.indexColumn]) ? this.backgroundActiveRow = e.row[this.indexColumn] : ((e.type != ActionsType.DBL_CLICK) ? this.backgroundActiveRow = null : '');
(e.type == ActionsType.CLICK) ? this.click.emit({ name: e.type, row: e.row }) : this.dblclick.emit({ name: e.type, row: e.row });
}
if (e.event.ctrlKey && !this.viewDialog && !e.event.altKey && !!this.config.multipleSelection) {
this.backgroundActiveRow = null;
if (!!this.rowsTempTableAdd.includes(e.row[this.indexColumn])) {
this.rowsTempTableAdd.forEach((r, i) => {
if (r === e.row[this.indexColumn]) {
this.rowsTempTableAdd.splice(i, 1);
}
});
}
else
this.rowsTempTableAdd.push(e.row[this.indexColumn]);
}
if (e.event.altKey && !this.viewDialog && !e.event.ctrlKey && !!this.config.multipleSelection) {
this.backgroundActiveRow = null;
if (!!this.alt) {
if (!!this.lastSortEvent)
this.sortRows(this.lastSortEvent);
if (this.firstIndexAltKey === e.row[this.indexColumn]) {
this.firstIndexAltKey = null;
this.alt = false;
this.rowsTempTableAdd.forEach((r, i) => {
if (r === e.row[this.indexColumn]) {
this.rowsTempTableAdd.splice(i, 1);
return;
}
});
return;
}
let found = false;
this.rows.forEach(r => {
if (!!this.asc) {
if (r[this.indexColumn] === e.row[this.indexColumn] && !!found) {
found = false;
if (!this.rowsTempTableAdd.includes(e.row[this.indexColumn]))
this.rowsTempTableAdd.push(e.row[this.indexColumn]);
return;
}
}
else {
if (this.firstIndexAltKey === r[this.indexColumn] && !!found) {
found = false;
return;
}
}
if (r[this.indexColumn] === this.firstIndexAltKey || r[this.indexColumn] === e.row[this.indexColumn] || !!found) {
if (r[this.indexColumn] === e.row[this.indexColumn] && !found) {
this.asc = false;
this.rowsTempTableAdd.push(r[this.indexColumn]);
}
(!!found) ? (!this.rowsTempTableAdd.includes(r[this.indexColumn]) ? this.rowsTempTableAdd.push(r[this.indexColumn]) : '') : found = true;
}
});
this.alt = false;
}
else {
this.firstIndexAltKey = e.row[this.indexColumn];
if (!this.rowsTempTableAdd.includes(this.firstIndexAltKey))
this.rowsTempTableAdd.push(e.row[this.indexColumn]);
this.alt = true;
this.asc = true;
}
}
if (!!e.event.shiftKey && !this.viewDialog && !e.event.ctrlKey && !!this.config.multipleSelection) {
this.rowsTempTableAdd = [];
this.firstIndexAltKey = null;
this.alt = false;
this.asc = true;
}
if (!!e.event.altKey && !!e.event.ctrlKey && !!this.config.multipleSelection) {
this.rowsTempTableAdd = this.rows.map(r => r[this.indexColumn]);
}
if (!!this.config.multipleSelection && (!!e.event.altKey || !!e.event.ctrlKey || !!e.event.shiftKey)) {
this.multipleSelection.emit({ name: ActionsType.MULTIPLE_SELECTION, rows: this.rowsTempTableAdd.map(data => this.data.find(r => r[this.indexColumn] === data)) || [] });
}
if (!!this.config.singleSelection && !e.event.altKey && !e.event.ctrlKey && !e.event.shiftKey && (e.type == ActionsType.CLICK || e.type == ActionsType.DBL_CLICK)) {
this.singleSelection.emit({ name: ActionsType.SINGLE_SELECTION, row: (!!this.backgroundActiveRow) ? e.row : null });
}
}
}
/**
* updateFilter
*
* Update the table values when modifying the filter
*
* @param val input filter value
*/
updateFilter(val) {
const value = val.toString().toLowerCase().trim();
const count = this.columns.length;
const keys = Object.keys(this.temp[0]);
const columnsFilter = this.selectedColumnsFilter.map(c => c.item_id);
this.rows = this.temp.filter(item => {
let keysColumn = Object.keys(item);
for (let i = 0; i < count; i++) {
if (!!columnsFilter.includes(keysColumn[i]) &&
keysColumn[i] != this.indexColumn &&
(item[keys[i]] &&
item[keys[i]]
.toString()
.toLowerCase()
.indexOf(value) !== -1) ||
!value) {
return true;
}
}
});
}
/**
* onSort
*
* Recive the event when sorting the table
*/
onSort(event) {
this.lastSortEvent = event;
this.sortRows(event);
}
/**
* getAll
*
* Get all the records in the table
*/
getAll() {
let data = this.data;
this.temp = data;
this.rows = [...this.temp];
}
/**
* updateValue
*
* Update table cell value
*/
updateValue(event, cell, rowIndex) {
let row = null;
let column = null;
let oldValue = null;
let newValue = null;
let result = false;
this.editing[rowIndex + '-' + cell] = false;
this.rows.forEach((r) => tslib_1.__awaiter(this, void 0, void 0, function* () {
if (r[this.indexColumn] === rowIndex) {
column = this.columns.find(c => c.prop === cell);
oldValue = r[cell];
newValue = event.target.value;
if (!!this.beforeAction &&
this.actionsTocontrol.includes(ActionsType.UPDATE_ROW) &&
!(yield this.beforeAction.call(this, { name: ActionsType.UPDATE_ROW, row: Object.assign({}, r), cell: { column: column, oldValue: oldValue, newValue: newValue } })))
return;
r[cell] = event.target.value;
row = Object.assign({}, r);
result = true;
}
}));
this.rows = [...this.rows];
this.updateSumaryColumns();
if (oldValue === newValue || !result)
return;
this.columns.filter(c => !!c.action).forEach(p => delete row[p.prop]);
this.updateRow.emit({ name: ActionsType.UPDATE_ROW, row: row, cell: { column: column, oldValue: oldValue, newValue: newValue } });
}
/**
* sendEvent
*
* Sending the name of the event and the row to the parent
*/
sendEvent(name, row) {
let action = {
name: name,
row: row
};
this.event.emit(action);
}
/**
* toggleFullscreen
*
* Maximize table to full screen
*/
toggleFullscreen() {
this.fullscreen = !this.fullscreen;
this.resize(10);
}
/**
* sortRows
*
* Sorts the rows as they are visually found in the table
*/
sortRows(sortEvent) {
let dir = "asc";
let prop = "";
if (!!sortEvent) {
dir = sortEvent.sorts[0].dir;
prop = sortEvent.sorts[0].prop;
const column = this.columns.find(c => c.prop === prop);
this.rows.sort(function (a, b) {
try {
let res = (a[prop].toString().localeCompare(b[prop], undefined, { numeric: column.sort.numeric }));
return (dir == 'asc') ? res : -1 * res;
}
catch (err) {
console.warn("Extended localeCompare() not supported in this browser.");
return (a[prop].toString().localeCompare(b[prop]));
}
});
}
}
/**
* export
*
* Build the object for export file and call the service to export it
*/
export(type) {
let columnsExport = this.columns.filter(c => !c.hide && !c.action && !!c.visible);
switch (type) {
case ExportsType.EXCEL:
let dataExport = [];
if (!!this.lastSortEvent)
this.sortRows(this.lastSortEvent);
this.rows.forEach(row => {
let obj = {};
columnsExport.forEach(column => {
obj[column.name] = row[column.prop];
});
dataExport.push(obj);
});
this.ngxTableService.exportAsExcelFile(dataExport, this.name, columnsExport.length);
break;
case ExportsType.PDF:
let nameColumns = columnsExport.map(c => c.name);
let propColumns = columnsExport.map(c => c.prop);
let rowsExportPdf = this.rows.map(r => {
let row = [];
propColumns.forEach(prop => {
row.push(r[prop]);
});
return row;
});
this.ngxTableService.exportAsPdf(this.name, [nameColumns], rowsExportPdf);
break;
default:
}
}
/**
* openDialog
*
* Build a dialog with the selected elements
*/
openDialog() {
const rows = this.rowsTempTableAdd.map(data => this.data.find(r => r[this.indexColumn] === data));
this.dialog.open(NgxTableDialogComponent, {
width: '80vw',
height: 'auto',
data: {
name: this.name + ' ' + this.config.language.generated,
rows: rows,
columns: this.columns,
config: this.config
}
});
}
/**
* closeDialog
*
* Close dialog
*/
closeDialog() {
this.dialog.closeAll();
this.resize(100);
}
/**
* resize
*
* Resize table
*/
resize(time) {
setTimeout(() => window.dispatchEvent(new Event('resize')), time);
}
/**
* addColumn
*
* Add a new column to the table
*/
addColumn() {
this.dialog.open(EditColumnDialogComponent, {
width: '40vw',
height: 'auto',
data: {
action: ActionColumnType.ADD,
nColumns: this.columns.filter(c => (!c.hide && !c.action)).length + 1,
config: this.config
}
}).afterClosed().subscribe((result) => tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!!result && !!result.name && !!result.name.length) {
const functionsType = FunctionTypes;
const functions = [];
result.functions.map((f, i) => {
if (!!f) {
functions.push({ type: functionsType[i].type, unit: (!!result.unitsFuntions[i]) ? result.unitsFuntions[i] : '' });
}
});
const newColumn = {
prop: `c-${this.indexNewColumn}`,
name: result.name.charAt(0).toUpperCase() + result.name.slice(1),
editable: result.editable,
sumary: functions,
predefinedData: result.predefined
};
if (!!this.beforeAction && this.actionsTocontrol.includes(ActionsType.NEW_COLUMN) && !(yield this.beforeAction.call(this, { name: ActionsType.NEW_COLUMN, column: new ColumnTableModel(newColumn) })))
return;
this.data.forEach(r => Object.assign(r, { [newColumn.prop]: result.predefined }));
const newPosition = (!this.columns[0].hide) ? result.position - 1 : result.position;
if (newPosition == this.columns.length)
this.columns.push(new ColumnTableModel(newColumn));
else
this.columns.splice(newPosition, 0, new ColumnTableModel(newColumn));
this.indexNewColumn++;
this.buildFilterByColumns();
const numSumaryColumns = !!this.sumaryColumns.length;
this.sumaryColumns = this.columns.filter(c => !!c.visible && !!new ColumnTableModel(c).sumary.length);
this.updateSumaryColumns();
if (numSumaryColumns !== !!this.sumaryColumns.length)
this.resize(10);
this.newColumn.emit({ name: ActionsType.NEW_COLUMN, column: new ColumnTableModel(newColumn) });
}
}));
;
}
/**
* editColumn
*
* Edit a column from the table
*/
editColumn() {
this.dialog.open(EditColumnDialogComponent, {
width: '40vw',
height: 'auto',
data: {
action: ActionColumnType.EDIT,
columns: this.columns.filter(c => (!c.hide && !c.action)),
config: this.config
}
}).afterClosed().subscribe((result) => tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!!result && !!result.name && !!result.name.length && !!result.column) {
const functionsType = FunctionTypes;
const functions = [];
result.functions.map((f, i) => {
if (!!f) {
functions.push({ type: functionsType[i].type, unit: (!!result.unitsFuntions[i]) ? result.unitsFuntions[i] : '' });
}
});
const newPosition = (!this.columns[0].hide) ? result.newPosition - 1 : result.newPosition;
const selecColumn = (!this.columns[0].hide) ? result.column - 1 : result.column;
const oldColumn = Object.assign({}, this.columns[selecColumn]);
const columnTempReview = Object.assign({}, oldColumn);
columnTempReview.name = result.name;
columnTempReview.editable = result.editable;
columnTempReview.sumary = functions;
if (!!this.beforeAction &&
this.actionsTocontrol.includes(ActionsType.EDIT_COLUMN) &&
!(yield this.beforeAction.call(this, { name: ActionsType.EDIT_COLUMN, oldColumn: oldColumn, updatedColumn: new ColumnTableModel(columnTempReview) })))
return;
this.columns[selecColumn].name = result.name;
this.columns[selecColumn].editable = result.editable;
this.columns[selecColumn].sumary = functions;
const columnTemp = this.columns.splice(selecColumn, 1);
if (newPosition == this.columns.length)
this.columns.push(new ColumnTableModel(columnTemp[0]));
else
this.columns.splice(newPosition, 0, new ColumnTableModel(columnTemp[0]));
this.columnsFilterList = this.selectedColumnsFilter = this.columns.filter(col => !col.hide && !col.action && !!col.visible && !!col.filtered).map(col => Object.assign({ item_id: col.prop, item_text: col.name }));
const numSumaryColumns = !!this.sumaryColumns.length;
this.sumaryColumns = this.columns.filter(c => !!c.visible && !!new ColumnTableModel(c).sumary.length);
this.updateSumaryColumns();
this.editColumnOuput.emit({ name: ActionsType.EDIT_COLUMN, oldColumn: oldColumn, updatedColumn: new ColumnTableModel(columnTemp[0]) });
if (numSumaryColumns !== !!this.sumaryColumns.length)
this.resize(10);
}
}));
;
}
/**
* deleteColumn
*
* Remove a column from the table
*/
deleteColumn() {
this.dialog.open(EditColumnDialogComponent, {
width: '40vw',
height: 'auto',
data: {
action: ActionColumnType.DELETE,
columns: this.columns.filter(c => (!c.hide && !c.action)),
config: this.config
}
}).afterClosed().subscribe((result) => tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!!result && !!result.column) {
const selecColumn = (!this.columns[0].hide) ? result.column - 1 : result.column;
const idColumn = this.columns[selecColumn].prop;
if (!!this.beforeAction && this.actionsTocontrol.includes(ActionsType.DELETE_COLUMN) && !(yield this.beforeAction.call(this, { name: ActionsType.DELETE_COLUMN, column: this.columns[selecColumn] })))
return;
const deleteColumn = this.columns.splice(selecColumn, 1);
this.buildFilterByColumns();
this.rows.forEach(r => delete r[idColumn]);
const numSumaryColumns = !!this.sumaryColumns.length;
this.sumaryColumns = this.columns.filter(c => !!c.visible && !!new ColumnTableModel(c).sumary.length);
this.updateSumaryColumns();
this.deleteColumnOuput.emit({ name: ActionsType.DELETE_COLUMN, column: deleteColumn[0] });
if (numSumaryColumns !== !!this.sumaryColumns.length)
this.resize(10);
}
}));
}
/**
* updateSumaryColumns
*
* Update the data of the sumary displayed in the footer
*/
updateSumaryColumns() {
this.dataSumary = [];
this.sumaryColumns.forEach(c => {
c.sumary.forEach(sumary => {
switch (sumary.type) {
case SumaryTypes.SUM:
let sum = 0;
this.rows.forEach(r => {
if (!!this.isNumeric(r[c.prop]))
sum += parseFloat(r[c.prop]);
});
this.dataSumary.push({ text: this.config.language.total, column: c.name, data: sum, unit: sumary.unit });
break;
case SumaryTypes.AVERAGE:
let elements = 0;
let total = 0;
this.rows.forEach(r => {
if (!!this.isNumeric(r[c.prop])) {
total += parseFloat(r[c.prop]);
}
elements++;
});
this.dataSumary.push({ text: this.config.language.avarage, column: c.name, data: (!!total) ? (total / elements).toFixed(2) : 0, unit: sumary.unit });
break;
case SumaryTypes.MAX:
let max = 0;
this.rows.forEach(r => {
if (!!this.isNumeric(r[c.prop]) && parseFloat(r[c.prop]) > max)
max = parseFloat(r[c.prop]);
});
this.dataSumary.push({ text: this.config.language.maximum, column: c.name, data: max, unit: sumary.unit });
break;
case SumaryTypes.MIN:
let min = (!!this.rows.length && !!this.isNumeric(this.rows[0][c.prop])) ? parseFloat(this.rows[0][c.prop]) : 0;
this.rows.forEach(r => {
if (!!this.isNumeric(r[c.prop]) && parseFloat(r[c.prop]) < min)
min = parseFloat(r[c.prop]);
});
this.dataSumary.push({ text: this.config.language.minimum, column: c.name, data: min, unit: sumary.unit });
break;
default:
}
});
});
}
/**
* isNumeric
*
* Check if a data is numeric
*/
isNumeric(value) {
return !isNaN(parseFloat(value)) && isFinite(value);
}
/**
* checkPredefinedDataColumn
*
* Enter default data to columns that have the predefinedData property only if it is not already defined in the row
*/
checkPredefinedDataColumn() {
const columnsPredefinedData = this.columns.filter(c => !!c.predefinedData);
columnsPredefinedData.forEach(c => {
this.data.forEach(r => {
if (!r.hasOwnProperty(c.prop))
r[c.prop] = c.predefinedData;
});
});
}
/**
* configureColumns
*
* Open the modal to configure the visibility, order and option to set columns
*/
configureColumns() {
const dialogConfig = Object.assign(new MatDialogConfig(), {
disableClose: true,
autoFocus: true,
top: 0,
right: 0,
panelClass: 'right-fixed',
data: {
columns: this.columns.filter(col => !col.hide && !col.action),
config: this.config
}
});
const dialog = this.dialog.open(GridColumnsComponent, dialogConfig);
dialog.afterClosed().subscribe(data => {
if (!data)
return;
let columns = [];
this.columns.forEach(c => {
if (!!c.hide)
columns.push(new ColumnTableModel(c));
});
data.forEach(c => columns.push(new ColumnTableModel(c)));
this.columns.forEach(c => {
if (!!c.action)
columns.push(new ColumnTableModel(c));
});
this.columns = columns;
this.buildFilterByColumns();
const numSumaryColumns = !!this.sumaryColumns.length;
this.sumaryColumns = this.columns.filter(c => c.visible && !!new ColumnTableModel(c).sumary.length);
this.updateSumaryColumns();
if (numSumaryColumns !== !!this.sumaryColumns.length)
this.resize(10);
});
}
ngOnDestroy() {
if (!!this.subscriptionChanges)
this.subscriptionChanges.unsubscribe();
}
};
NgxTableComponent.ctorParameters = () => [
{ type: NgxTableService },
{ type: NotificationNgxService },
{ type: MatDialog }
];
tslib_1.__decorate([
ViewChild('search', { static: false })
], NgxTableComponent.prototype, "search", void 0);
tslib_1.__decorate([
Input()
], NgxTableComponent.prototype, "name", void 0);
tslib_1.__decorate([
Input()
], NgxTableComponent.prototype, "config", void 0);
tslib_1.__decorate([
Input()
], NgxTableComponent.prototype, "columns", void 0);
tslib_1.__decorate([
Input()
], NgxTableComponent.prototype, "data", void 0);
tslib_1.__decorate([
Input()
], NgxTableComponent.prototype, "viewDialog", void 0);
tslib_1.__decorate([
Input()
], NgxTableComponent.prototype, "beforeAction", void 0);
tslib_1.__decorate([
Input()
], NgxTableComponent.prototype, "actionsTocontrol", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "event", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "click", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "dblclick", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "singleSelection", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "multipleSelection", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "visibleDataTable", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "dataTable", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "updateRow", void 0);
tslib_1.__decorate([
Output()
], NgxTableComponent.prototype, "newColumn", void 0);
tslib_1.__decorate([
Output(ActionsType.EDIT_COLUMN)
], NgxTableComponent.prototype, "editColumnOuput", void 0);
tslib_1.__decorate([
Output(ActionsType.DELETE_COLUMN)
], NgxTableComponent.prototype, "deleteColumnOuput", void 0);
tslib_1.__decorate([
HostListener('window:resize', ['$event'])
], NgxTableComponent.prototype, "onResize", null);
NgxTableComponent = tslib_1.__decorate([
Component({
selector: 'ngx-table-powerfull',
template: "<div class=\"row\" [ngClass]=\"{ 'maximize': !!fullscreen }\">\r\n <div class=\"col-12 ngx-table-powerfull\">\r\n <div [ngClass]=\"{'card': (!!config.cardBody || !!fullscreen) && (!viewDialog || !!fullscreen)}\" >\r\n <div class=\"card-body\" [ngClass]=\"{ 'table-dialog': !!viewDialog && !!fullscreen }\">\r\n <h4 class=\"card-title\" [ngClass]=\"{ 'min-height': !!config.visibleTitle || !!config.fullscreen }\">{{ !!config.visibleTitle ? name : '' }}</h4>\r\n\r\n <div class=\"row mt-4 px-4\">\r\n <button *ngIf=\"!!config.fullscreen\" [ngClass]=\"{ 'button-fullscreen': !viewDialog, 'button-fullscreen-dialog': !!viewDialog, 'button-fullscreen-dialog-f': !!viewDialog && !!fullscreen }\" (click)=\"toggleFullscreen()\">\r\n <i *ngIf=\"!fullscreen\" class=\"material-icons\" [matTooltip]=\"config.language.maximize\">fullscreen</i>\r\n <i *ngIf=\"!!fullscreen\" class=\"material-icons\" [matTooltip]=\"config.language.restore\">fullscreen_exit</i>\r\n </button>\r\n\r\n <i *ngIf=\"!!viewDialog\" class=\"material-icons\" [ngClass]=\"{ 'default-close': !fullscreen, 'fullscreen-close': !!fullscreen }\" (click)=\"closeDialog()\" [matTooltip]=\"config.language.close\">close</i>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <div class=\"row\" style=\"min-height: 48px !important;\">\r\n\r\n <div class=\"col-12 filter-search\" [ngClass]=\"{'col-lg-6': !!rowsTempTableAdd.length && !!config.viewDialogTable , 'col-lg-7': !rowsTempTableAdd.length || !config.viewDialogTable }\">\r\n\r\n <mat-form-field *ngIf=\"!!config.filter && config.classTable === 'material'\" class=\"example-full-width\" style=\"width: 100%; margin-top: -10px !important;\">\r\n <mat-label>{{ config.language.filterResults }}</mat-label>\r\n <input matInput #search id=\"search\" type=\"text\">\r\n </mat-form-field>\r\n\r\n <input #search *ngIf=\"!!config.filter && config.classTable === 'boostrap'\" id=\"search\" class=\"form-control\" type=\"text\" [placeholder]=\"config.language.filterResults\"/>\r\n\r\n <ng-multiselect-dropdown\r\n *ngIf=\"!!selectColumnsFilter\"\r\n class=\"selected-columns\"\r\n [placeholder]=\"config.language.selectColumns\"\r\n [data]=\"columnsFilterList\"\r\n [(ngModel)]=\"selectedColumnsFilter\"\r\n [settings]=\"dropdownSettings\"\r\n (ngModelChange)=\"onChangeSelectFilter()\"\r\n >\r\n </ng-multiselect-dropdown>\r\n\r\n </div>\r\n\r\n <div class=\"col-12 col-lg-1 setting\">\r\n <i *ngIf=\"!selectColumnsFilter && !!config.filter && !!config.filterByColumn\" class=\"material-icons settings-search\" [matTooltip]=\"config.language.configureFilter\" (click)=\"openConfigFilter()\">settings</i>\r\n <i *ngIf=\"!!selectColumnsFilter && !!config.filter && !!config.filterByColumn\" class=\"material-icons settings-search\" [matTooltip]=\"config.language.closeConfigure\" (click)=\"openConfigFilter()\">close</i>\r\n </div>\r\n\r\n <div class=\"col-12 text-right\" [ngClass]=\"{'col-lg-5': !!rowsTempTableAdd.length && !!config.viewDialogTable , 'col-lg-4': !rowsTempTableAdd.length || !config.viewDialogTable}\">\r\n \r\n <button *ngIf=\"!!rowsTempTableAdd.length && !!config.viewDialogTable\" class=\"btn btnPrimary-outline-generate\" (click)=\"openDialog()\">\r\n {{ config.multipleButtonText }}\r\n {{ (!!config.visibleNumberRowsButton) ? ((rowsTempTableAdd.length > 1 ) ? rowsTempTableAdd.length + ' ' + config.language.rows : rowsTempTableAdd.length + ' ' + config.language.row) : ''}}\r\n </button>\r\n\r\n <button *ngIf=\"!!rows.length && (!!config.exportExcel || !!config.exportPdf)\" mat-raised-button class=\"btn btn-export btnPrimary-outline\" [matMenuTriggerFor]=\"exportMenu\">\r\n {{ config.language.export }} <i class=\"material-icons float-right mt-2\">arrow_drop_up</i>\r\n </button>\r\n \r\n <mat-menu #exportMenu=\"matMenu\" class=\"menu-more\" yPosition=\"above\" xPosition=\"after\">\r\n <button *ngIf=\"!!config.exportExcel\" class=\"mat-menu-item\" (click)=\"export(1)\">\r\n <i class=\"fa fa-file-excel-o\" style=\"margin: .8rem 1rem 0 -.4em; font-size: 20px;\"></i>EXCEL\r\n </button>\r\n <button *ngIf=\"!!config.exportPdf\" class=\"mat-menu-item\" (click)=\"export(2)\">\r\n <i class=\"fa fa-file-pdf-o\" style=\"margin: .8rem 1rem 0 -.4em; font-size: 20px;\"></i>PDF\r\n </button>\r\n </mat-menu>\r\n\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"!!config.editableColumns\" class=\"col-12 col-lg-12 add-column\">\r\n <i *ngIf=\"!!config.configureColumns\" class=\"material-icons configure\" [matTooltip]=\"config.language.configureColumns\" (click)=\"configureColumns()\">view_headline</i>\r\n <i *ngIf=\"!!config.editColumn\" class=\"material-icons edit\" [matTooltip]=\"config.language.editColumn\" (click)=\"editColumn()\">edit</i>\r\n <i *ngIf=\"!!config.addColumn\" class=\"material-icons add\" [matTooltip]=\"config.language.newColumn\" (click)=\"addColumn()\">add</i>\r\n <i *ngIf=\"!!config.deleteColumn\" class=\"material-icons delete\" [matTooltip]=\"config.language.deleteColumn\" (click)=\"deleteColumn()\">delete</i>\r\n </div>\r\n\r\n <ngx-datatable\r\n #table \r\n class=\"material\"\r\n [ngClass]=\"{'striped': !!config.striped }\"\r\n [style.height]=\"(!!viewDialog) ? \r\n ((!!fullscreen) ? (!!selectColumnsFilter ? 'calc(100vh - '+ height.fullscreenFilter +'px)' : 'calc(100vh - ' + height.fullscreen +'px)' ) : '400px') \r\n :'calc(100vh - ' + ((!!fullscreen) ? \r\n (!!selectColumnsFilter ? height.fullscreenFilter : height.fullscreen ) \r\n : (!config.collapsed ?\r\n (!!selectColumnsFilter ? (!!config.editableColumns ? config.subtractHeightCollapsed + 55 : config.subtractHeightCollapsed + 40 ): (!!config.editableColumns ? config.subtractHeightCollapsed + 15 : config.subtractHeightCollapsed )): \r\n (!!selectColumnsFilter ? (!!config.editableColumns ? config.subtractHeight + 55 : config.subtractHeight + 40 ) : (!!config.editableColumns ? config.subtractHeight + 15 : config.subtractHeight) )) ) + 'px)'\" \r\n [columns]=\"columns\" \r\n [rows]=\"rows\"\r\n [columnMode]=\"'force'\"\r\n [headerHeight]=\"config.headerHeight\"\r\n [footerHeight]=\"(!!dataSumary.length) ? (config.sumaryFooterHeight + config.footerHeight) : config.footerHeight\"\r\n [rowHeight]=\"config.rowHeight\"\r\n [limit]=\"config.limitResult\"\r\n [scrollbarV]=\"(!!config.limitResult) ? false : true\"\r\n [scrollbarH]=\"(!!config.limitResult) ? false : true\"\r\n [rowClass]=\"getRowClass\" \r\n [messages]=\"{ emptyMessage: config.language.emptyMessage }\"\r\n [reorderable]=\"false\"\r\n (activate)=\"onActivate($event)\"\r\n (sort)=\"onSort($event)\"\r\n >\r\n\r\n <ng-container *ngFor=\"let c of columns;let i = index\">\r\n \r\n <ngx-datatable-column name=\"{{ c.name }}\" prop=\"{{ c.prop }}\" *ngIf=\"!c.hide && !!c.visible\" [sortable]=\"!!config.sortable && !!c.sortable\" [frozenLeft]=\"!!c.fixed ? true : false\">\r\n\r\n <ng-template let-row=\"row\" ngx-datatable-cell-template>\r\n\r\n <span \r\n *ngIf=\"!editing[row[indexColumn] + '-' + c.prop]\" \r\n [matTooltip]=\"(!!c.tooltip) ? ((!!c.tooltipText.length) ? c.tooltipText : row[c.prop] ): null\"\r\n [innerHTML]=\"row[c.prop]\" (click)=\"(!!c.action) ? sendEvent(c.action, row) : ''\" \r\n (dblclick)=\"(!!c.editable && !c.action) ? editing[row[indexColumn] + '-' + c.prop] = true : ''\"\r\n >\r\n </span>\r\n\r\n <i *ngIf=\"!editing[row[indexColumn] + '-' + c.prop] && !!c.editable\" \r\n class=\"material-icons edit-icon\"\r\n (click)=\"editing[row[indexColumn] + '-' + c.prop] = true\">\r\n edit\r\n </i>\r\n\r\n <input \r\n *ngIf=\"editing[row[indexColumn] + '-' + c.prop] && !!c.editable && !c.action\"\r\n autofocus\r\n (blur)=\"updateValue($event, c.prop, row[indexColumn])\"\r\n type=\"text\"\r\n [value]=\"row[c.prop]\"\r\n />\r\n\r\n </ng-template>\r\n </ngx-datatable-column>\r\n </ng-container>\r\n\r\n <ngx-datatable-footer *ngIf=\"!!dataSumary.length\">\r\n <ng-template\r\n ngx-datatable-footer-template\r\n let-rowCount=\"rowCount\"\r\n let-pageSize=\"pageSize\"\r\n let-selectedCount=\"selectedCount\"\r\n let-curPage=\"curPage\"\r\n let-offset=\"offset\"\r\n >\r\n <div class=\"container-footer\">\r\n \r\n <div class=\"header-footer\" [style.height]=\"(config.sumaryFooterHeight - 30 )+ 'px'\" [ngClass]=\"{ 'sumary-right': config.positionSumary == 'right' }\">\r\n <div class=\"data-column\" *ngFor=\"let data of dataSumary\" style=\"display:inline-block\">\r\n <strong style=\"margin-right: 10px;\">{{ data.text + ': '}}</strong><span style=\"margin-right: 5px;\">{{ data.column + ':' }}</span>{{data.data + ' ' + data.unit }}\r\n </div>\r\n </div>\r\n\r\n <hr style=\"width:100%\" />\r\n\r\n <div class=\"bottom-f