UNPKG

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
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