import { Injectable } from "@angular/core"; import { ColumnType, SortDirection, TableColumn, TableSort } from "../../models"; import { cloneDeep, orderBy } from "lodash"; import { TranslateService } from "@ngx-translate/core"; export interface TableSortSettings { sorts: TableSort[]; sortedColumns: Object; } export interface TableSortResults { displayedRows: any[]; sorts: TableSort[]; } @Injectable() export class TableSortService { constructor(private translateService: TranslateService) {} toggleSort(column: string, sorts: TableSort[]): TableSortSettings { const existingColumnSort = sorts.find(x => x.column === column); if (!existingColumnSort) { sorts.push({ column: column, sortDirection: SortDirection.ASCENDING}); } else if (existingColumnSort.sortDirection === SortDirection.ASCENDING) { sorts.splice(sorts.indexOf(existingColumnSort), 1); sorts.push({ column: column, sortDirection: SortDirection.DESCENDING}); } else { sorts.splice(sorts.indexOf(existingColumnSort), 1); } let sortedColumns: Object = Object.create(null); if (sorts != null && sorts.length > 0) { sortedColumns = sorts.reduce((r, s) => { r[s.column] = s.sortDirection; return r; }, Object.create(null)); } return { sorts, sortedColumns }; } getSortedColumnsObject(sorts: TableSort[]): Object { let sortedColumns: Object = Object.create(null); if (sorts != null && sorts.length > 0) { sortedColumns = sorts.reduce((r, s) => { r[s.column] = s.sortDirection; return r; }, Object.create(null)); } return sortedColumns; } sortColumns(sorts: TableSort[], displayedColumns: TableColumn[], displayedRows: any[], rowTrackByProp: string): TableSortResults { const sortProps: string[] = []; const sortDirections: any = []; let sortsToRemove: TableSort[] = []; for (let i = 0; i < sorts.length; i++) { const column = displayedColumns.find(x => x.prop === sorts[i].column); if (column == null) { sortsToRemove.push(sorts[i]); continue; } sortProps.push(sorts[i].column); sortDirections.push(sorts[i].sortDirection); } if (sortsToRemove.length > 0) { sorts = sorts.filter(x => sortsToRemove.indexOf(x) === -1); } let rowsCopy = cloneDeep(displayedRows); this.formatColumnValuesForSorting(rowsCopy, sortProps, displayedColumns); rowsCopy = orderBy(rowsCopy, sortProps, sortDirections); const tempRows: any[] = []; for (let j = 0; j < rowsCopy.length; j++) { const row = displayedRows.find(x => x[rowTrackByProp] === rowsCopy[j][rowTrackByProp]); tempRows.push(row); } return { displayedRows: tempRows, sorts }; } private formatColumnValuesForSorting(rows: any[], sortProps: any[], columns: TableColumn[]) { for (let i = 0; i < sortProps.length; i++) { const column = columns.find(x => x.prop === sortProps[i]); if (column != null) { switch (column.columnType) { case ColumnType.TEXT: this.formatTextColumn(rows, sortProps[i], column.translateValue); break; case ColumnType.NUMBER: this.formatNumberColumn(rows, sortProps[i]); break; case ColumnType.ENUM_ICON: this.formatEnumIconColumn(rows, sortProps[i], column); break; case ColumnType.TIME_SINCE: this.formatTimeSinceColumn(rows, sortProps[i]); } } } } private formatTextColumn(rows: any[], sortProp: string, translate?: boolean) { for (let i = 0; i < rows.length; i++) { if (rows[i][sortProp] == null) { rows[i][sortProp] = ''; } else { if (translate) { rows[i][sortProp] = this.translateService.instant(rows[i][sortProp]); } rows[i][sortProp] = rows[i][sortProp].toLowerCase(); } } } private formatNumberColumn(rows: any[], sortProp: string) { for (let i = 0; i < rows.length; i++) { if (rows[i][sortProp] == null) { continue; } if (typeof rows[i][sortProp] === 'string' || rows[i][sortProp] instanceof String) { rows[i][sortProp] = +rows[i][sortProp]; } } } private formatEnumIconColumn(rows: any[], sortProp: string, column: TableColumn) { if (column.enumIconOptions != null) { column.enumIconOptions.forEach(enumIconOption => { const rowsWithEnumValue = rows.filter(x => x[sortProp] == enumIconOption.enumValue); rowsWithEnumValue.forEach(row => { row[sortProp] = enumIconOption.displayValue != null ? enumIconOption.translateDisplayValue ? this.translateService.instant(enumIconOption.displayValue) : enumIconOption.displayValue : row[sortProp]; }); }); } } private formatTimeSinceColumn(rows: any[], sortProp: string) { const currentTime = new Date(); for (let i = 0; i < rows.length; i++) { if (rows[i][sortProp] == null) { continue; } if (typeof rows[i][sortProp].getTime === 'function') { rows[i][sortProp] = (currentTime.getTime() - rows[i][sortProp].getTime()); } else if (typeof rows[i][sortProp] === 'string' || rows[i][sortProp] instanceof String) { const rowDate = new Date(rows[i][sortProp]) if(rowDate.toString() !== 'Invalid Date') { rows[i][sortProp] = (currentTime.getTime() - rowDate.getTime()); } } } } }