From e569cddf5571a2235d631f95701bcb57688bc302 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Fri, 18 May 2018 17:38:14 -0400 Subject: [PATCH] LP#1775466 ng-lint updates Signed-off-by: Bill Erickson --- Open-ILS/src/eg2/src/app/share/grid/grid.ts | 559 +++++++++++++++------------- 1 file changed, 294 insertions(+), 265 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid.ts b/Open-ILS/src/eg2/src/app/share/grid/grid.ts index 232ad32402..2d8af7900f 100644 --- a/Open-ILS/src/eg2/src/app/share/grid/grid.ts +++ b/Open-ILS/src/eg2/src/app/share/grid/grid.ts @@ -3,7 +3,7 @@ */ import {TemplateRef} from '@angular/core'; import {Observable} from 'rxjs/Observable'; -import {Subscription} from "rxjs/Subscription"; +import {Subscription} from 'rxjs/Subscription'; import {EgIdlService, EgIdlObject} from '@eg/core/idl.service'; import {EgOrgService} from '@eg/core/org.service'; import {EgStoreService} from '@eg/core/store.service'; @@ -12,6 +12,243 @@ import {Pager} from '@eg/share/util/pager'; const MAX_ALL_ROW_COUNT = 10000; +export class EgGridColumn { + name: string; + path: string; + label: string; + flex: number; + align: string; + hidden: boolean; + visible: boolean; + sort: number; + idlClass: string; + idlFieldDef: any; + datatype: string; + cellTemplate: TemplateRef; + isIndex: boolean; + isDragTarget: boolean; + isSortable: boolean; + isMultiSortable: boolean; +} + +export class EgGridColumnSet { + columns: EgGridColumn[]; + idlClass: string; + indexColumn: EgGridColumn; + isSortable: boolean; + isMultiSortable: boolean; + stockVisible: string[]; + + constructor(idlClass?: string) { + this.columns = []; + this.stockVisible = []; + this.idlClass = idlClass; + } + + add(col: EgGridColumn) { + // avoid dupes + if (this.getColByName(col.name)) { return; } + + if (col.isIndex) { this.indexColumn = col; } + if (!col.flex) { col.flex = 2; } + if (!col.label) { col.label = col.name; } + if (!col.align) { col.align = 'left'; } + if (!col.datatype) { col.datatype = 'text'; } + + col.visible = !col.hidden; + + // track which fields are visible on page load. + if (col.visible) { + this.stockVisible.push(col.name); + } + + this.applyColumnSortability(col); + + this.columns.push(col); + } + + getColByName(name: string): EgGridColumn { + return this.columns.filter(c => c.name === name)[0]; + } + + reset() { + this.columns.forEach(col => { + col.flex = 2; + col.sort = 0; + col.align = 'left'; + col.visible = this.stockVisible.includes(col.name); + }); + } + + applyColumnSortability(col: EgGridColumn) { + // column sortability defaults to the sortability of the column set. + if (col.isSortable === undefined && this.isSortable) { + col.isSortable = true; + } + + if (col.isMultiSortable === undefined && this.isMultiSortable) { + col.isMultiSortable = true; + } + + if (col.isMultiSortable) { + col.isSortable = true; + } + } + + displayColumns(): EgGridColumn[] { + return this.columns.filter(c => c.visible); + } + + insertBefore(source: EgGridColumn, target: EgGridColumn) { + let targetIdx = -1; + let sourceIdx = -1; + this.columns.forEach((col, idx) => { + if (col.name === target.name) { targetIdx = idx; }}); + + this.columns.forEach((col, idx) => { + if (col.name === source.name) { sourceIdx = idx; }}); + + if (sourceIdx >= 0) { + this.columns.splice(sourceIdx, 1); + } + + this.columns.splice(targetIdx, 0, source); + } + + // Move visible columns to the front of the list. + moveVisibleToFront() { + const newCols = this.displayColumns(); + this.columns.forEach(col => { + if (!col.visible) { newCols.push(col); }}); + this.columns = newCols; + } + + moveColumn(col: EgGridColumn, diff: number) { + let srcIdx, targetIdx; + + this.columns.forEach((c, i) => { + if (c.name === col.name) { srcIdx = i; } + }); + + targetIdx = srcIdx + diff; + if (targetIdx < 0) { + targetIdx = 0; + } else if (targetIdx >= this.columns.length) { + // Target index follows the last visible column. + let lastVisible = 0; + this.columns.forEach((c, idx) => { + if (c.visible) { lastVisible = idx; } + }); + + // When moving a column (down) causes one or more + // visible columns to shuffle forward, our column + // moves into the slot of the last visible column. + // Otherwise, put it into the slot directly following + // the last visible column. + targetIdx = srcIdx <= lastVisible ? lastVisible : lastVisible + 1; + } + + // Splice column out of old position, insert at new position. + this.columns.splice(srcIdx, 1); + this.columns.splice(targetIdx, 0, col); + } + + compileSaveObject(): EgGridColumnPersistConf[] { + // only store information about visible columns. + const conf = this.displayColumns(); + + // scrunch the data down to just the needed info + return conf.map(col => { + const c: EgGridColumnPersistConf = {name : col.name}; + if (col.align !== 'left') { c.align = col.align; } + if (col.flex !== 2) { c.flex = Number(col.flex); } + if (Number(col.sort)) { c.sort = Number(c.sort); } + return c; + }); + } + + applyColumnSettings(conf: EgGridColumnPersistConf[]) { + if (!conf || conf.length === 0) { return; } + + const newCols = []; + + conf.forEach(colConf => { + const col = this.getColByName(colConf.name); + if (!col) { return; } // no such column in this grid. + + col.visible = true; + if (colConf.align) { col.align = colConf.align; } + if (colConf.flex) { col.flex = Number(colConf.flex); } + if (colConf.sort) { col.sort = Number(colConf.sort); } + + // Add to new columns array, avoid dupes. + if (newCols.filter(c => c.name === col.name).length === 0) { + newCols.push(col); + } + }); + + // columns which are not expressed within the saved + // configuration are marked as non-visible and + // appended to the end of the new list of columns. + this.columns.forEach(c => { + if (conf.filter(cf => cf.name === c.name).length === 0) { + c.visible = false; + newCols.push(c); + } + }); + + this.columns = newCols; + } +} + + +export class EgGridRowSelector { + indexes: {[string: string]: boolean}; + + constructor() { + this.clear(); + } + + // Returns true if all of the requested indexes exist in the selector. + contains(index: string | string[]): boolean { + const indexes = [].concat(index); + for (let i = 0; i < indexes.length; i++) { // early exit + if (!this.indexes[indexes[i]]) { + return false; + } + } + return true; + } + + select(index: string | string[]) { + const indexes = [].concat(index); + indexes.forEach(i => this.indexes[i] = true); + } + + deselect(index: string | string[]) { + const indexes = [].concat(index); + indexes.forEach(i => delete this.indexes[i]); + } + + // Returns the list of selected index values. + // in some contexts (template checkboxes) the value for an index is + // set to false to deselect instead of having it removed (via deselect()). + selected() { + return Object.keys(this.indexes).filter( + ind => Boolean(this.indexes[ind])); + } + + isEmpty(): boolean { + return this.selected().length === 0; + } + + clear() { + this.indexes = {}; + } +} + + + export class EgGridContext { pager: Pager; @@ -62,7 +299,7 @@ export class EgGridContext { this.getColumnsConfig(this.persistKey) .then(conf => this.columnSet.applyColumnSettings(conf)) .then(ok => this.dataSource.requestPage(this.pager)) - .then(ok => this.listenToPager()) + .then(ok => this.listenToPager()); } destroy() { @@ -77,21 +314,23 @@ export class EgGridContext { // Subscribe or unsubscribe to page-change events from the pager. listenToPager() { - if (this.pageChanges) return; + if (this.pageChanges) { return; } this.pageChanges = this.pager.onChange$.subscribe( val => this.dataSource.requestPage(this.pager)); // TODO: index rows as they arrive } ignorePager() { - if (!this.pageChanges) return; + if (!this.pageChanges) { return; } this.pageChanges.unsubscribe(); - this.pageChanges = null + this.pageChanges = null; } getRowIndex(row: any): any { - let col = this.columnSet.indexColumn; - if (!col) throw new Error('grid index column required'); + const col = this.columnSet.indexColumn; + if (!col) { + throw new Error('grid index column required'); + } return this.getRowColumnValue(row, col); } @@ -100,35 +339,39 @@ export class EgGridContext { getRowPosition(index: any): number { // for-loop for early exit for (let idx = 0; idx < this.dataSource.data.length; idx++) { - if (index == this.getRowIndex(this.dataSource.data[idx])) + if (index === this.getRowIndex(this.dataSource.data[idx])) { return idx; + } } } getRowByIndex(index: any): any { for (let idx = 0; idx < this.dataSource.data.length; idx++) { - if (index == this.getRowIndex(this.dataSource.data[idx])) + if (index === this.getRowIndex(this.dataSource.data[idx])) { return this.dataSource.data[idx]; + } } } // Returns all selected rows, regardless of whether they are // currently visible in the grid display. getSelectedRows(): any[] { - let selected = []; + const selected = []; this.rowSelector.selected().forEach(index => { - let row = this.getRowByIndex(index); - if (row) selected.push(row); + const row = this.getRowByIndex(index); + if (row) { + selected.push(row); + } }); return selected; } getRowColumnValue(row: any, col: EgGridColumn): string { let val; - if (typeof row[col.name] == 'function') { + if (typeof row[col.name] === 'function') { val = row[col.name](); } else { - val = row[col.name] + val = row[col.name]; } return this.format.transform({value: val, datatype: col.datatype}); } @@ -160,14 +403,16 @@ export class EgGridContext { } selectRowByPos(pos: number) { - let row = this.dataSource.data[pos]; - if (row) this.selectOneRow(this.getRowIndex(row)); + const row = this.dataSource.data[pos]; + if (row) { + this.selectOneRow(this.getRowIndex(row)); + } } selectPreviousRow() { - if (!this.lastSelectedIndex) return; - let pos = this.getRowPosition(this.lastSelectedIndex); - if (pos == this.pager.offset) { + if (!this.lastSelectedIndex) { return; } + const pos = this.getRowPosition(this.lastSelectedIndex); + if (pos === this.pager.offset) { this.toPrevPage().then(ok => this.selectLastRow(), err => {}); } else { this.selectRowByPos(pos - 1); @@ -175,9 +420,9 @@ export class EgGridContext { } selectNextRow() { - if (!this.lastSelectedIndex) return; - let pos = this.getRowPosition(this.lastSelectedIndex); - if (pos == (this.pager.offset + this.pager.limit - 1)) { + if (!this.lastSelectedIndex) { return; } + const pos = this.getRowPosition(this.lastSelectedIndex); + if (pos === (this.pager.offset + this.pager.limit - 1)) { this.toNextPage().then(ok => this.selectFirstRow(), err => {}); } else { this.selectRowByPos(pos + 1); @@ -193,7 +438,9 @@ export class EgGridContext { } toPrevPage(): Promise { - if (this.pager.isFirstPage()) return Promise.reject('on first'); + if (this.pager.isFirstPage()) { + return Promise.reject('on first'); + } // temp ignore pager events since we're calling requestPage manually. this.ignorePager(); this.pager.decrement(); @@ -202,7 +449,9 @@ export class EgGridContext { } toNextPage(): Promise { - if (this.pager.isLastPage()) return Promise.reject('on last'); + if (this.pager.isLastPage()) { + return Promise.reject('on last'); + } // temp ignore pager events since we're calling requestPage manually. this.ignorePager(); this.pager.increment(); @@ -211,7 +460,7 @@ export class EgGridContext { } getAllRows(): Promise { - let pager = new Pager(); + const pager = new Pager(); pager.offset = 0; pager.limit = MAX_ALL_ROW_COUNT; return this.dataSource.requestPage(pager); @@ -219,7 +468,7 @@ export class EgGridContext { // Returns a key/value pair object of visible column data as text. getRowAsFlatText(row: any): any { - let flatRow = {}; + const flatRow = {}; this.columnSet.displayColumns().forEach(col => { flatRow[col.name] = this.getColumnTextContent(row, col); @@ -232,7 +481,7 @@ export class EgGridContext { this.getAllRows().then(ok => { this.dataSource.data.forEach(row => { observer.next(this.getRowAsFlatText(row)); - }) + }); observer.complete(); }); }); @@ -241,7 +490,7 @@ export class EgGridContext { gridToCsv(): Promise { let csvStr = ''; - let columns = this.columnSet.displayColumns(); + const columns = this.columnSet.displayColumns(); // CSV header columns.forEach(col => { @@ -249,7 +498,7 @@ export class EgGridContext { csvStr += ','; }); - csvStr = csvStr.replace(/,$/,'\n'); + csvStr = csvStr.replace(/,$/, '\n'); return new Promise(resolve => { this.getAllRowsAsText().subscribe( @@ -258,7 +507,7 @@ export class EgGridContext { csvStr += this.valueToCsv(row[col.name]); csvStr += ','; }); - csvStr = csvStr.replace(/,$/,'\n'); + csvStr = csvStr.replace(/,$/, '\n'); }, err => {}, () => resolve(csvStr) @@ -270,8 +519,8 @@ export class EgGridContext { // prepares a string for inclusion within a CSV document // by escaping commas and quotes and removing newlines. valueToCsv(str: string): string { - str = ''+str; - if (!str) return ''; + str = '' + str; + if (!str) { return ''; } str = str.replace(/\n/g, ''); if (str.match(/\,/) || str.match(/"/)) { str = str.replace(/"/g, '""'); @@ -285,14 +534,16 @@ export class EgGridContext { // generate columns for all non-virtual fields on the IDL class if (this.columnSet.idlClass) { this.idl.classes[this.columnSet.idlClass].fields.forEach(field => { - if (field.virtual) return; - let col = new EgGridColumn(); + if (field.virtual) { return; } + const col = new EgGridColumn(); col.name = field.name; col.label = field.label || field.name; col.idlFieldDef = field; col.datatype = field.datatype; - if (field.name == this.idl.classes[this.columnSet.idlClass].pkey) + if (field.name === + this.idl.classes[this.columnSet.idlClass].pkey) { col.isIndex = true; + } this.columnSet.add(col); }); } @@ -300,9 +551,11 @@ export class EgGridContext { saveColumns(): Promise { - if (!this.persistKey) + if (!this.persistKey) { throw new Error('Grid persistKey required to save columns'); - let compiled: EgGridColumnPersistConf[] = this.columnSet.compileSaveObject(); + } + const compiled: EgGridColumnPersistConf[] = + this.columnSet.compileSaveObject(); return this.store.setItem('eg.grid.' + this.persistKey, compiled); } @@ -310,31 +563,12 @@ export class EgGridContext { // TODO: saveColumnsAsOrgSetting(...) getColumnsConfig(persistKey: string): Promise { - if (!persistKey) return Promise.resolve([]); + if (!persistKey) { return Promise.resolve([]); } return this.store.getItem('eg.grid.' + persistKey); } } -export class EgGridColumn { - name: string; - path: string; - label: string; - flex: number; - align: string; - hidden: boolean; - visible: boolean; - sort: number; - idlClass: string; - idlFieldDef: any; - datatype: string; - cellTemplate: TemplateRef; - isIndex: boolean; - isDragTarget: boolean; - isSortable: boolean; - isMultiSortable: boolean; -} - export class EgGridColumnPersistConf { name: string; flex?: number; @@ -342,166 +576,6 @@ export class EgGridColumnPersistConf { align?: string; } -export class EgGridColumnSet { - columns: EgGridColumn[]; - idlClass: string; - indexColumn: EgGridColumn; - isSortable: boolean; - isMultiSortable: boolean; - stockVisible: string[]; - - constructor(idlClass?: string) { - this.columns = []; - this.stockVisible = []; - this.idlClass = idlClass; - } - - add(col: EgGridColumn) { - // avoid dupes - if (this.getColByName(col.name)) return; - - if (col.isIndex) this.indexColumn = col; - if (!col.flex) col.flex = 2; - if (!col.label) col.label = col.name; - if (!col.align) col.align = 'left'; - if (!col.datatype) col.datatype = 'text'; - - col.visible = !col.hidden; - - // track which fields are visible on page load. - if (col.visible) this.stockVisible.push(col.name); - - this.applyColumnSortability(col); - - this.columns.push(col); - } - - getColByName(name: string): EgGridColumn { - return this.columns.filter(c => c.name == name)[0]; - } - - reset() { - this.columns.forEach(col => { - col.flex = 2; - col.sort = 0; - col.align = 'left'; - col.visible = this.stockVisible.includes(col.name); - }); - } - - applyColumnSortability(col: EgGridColumn) { - // column sortability defaults to the sortability of the column set. - if (col.isSortable === undefined && this.isSortable) - col.isSortable = true; - - if (col.isMultiSortable === undefined && this.isMultiSortable) - col.isMultiSortable = true; - - if (col.isMultiSortable) col.isSortable = true; - } - - displayColumns(): EgGridColumn[] { - return this.columns.filter(c => c.visible); - } - - insertBefore(source: EgGridColumn, target: EgGridColumn) { - let targetIdx = -1; - let sourceIdx = -1; - this.columns.forEach((col, idx) => { - if (col.name == target.name) targetIdx = idx; }); - - this.columns.forEach((col, idx) => { - if (col.name == source.name) sourceIdx = idx; }); - - if (sourceIdx >= 0) - this.columns.splice(sourceIdx, 1); - - this.columns.splice(targetIdx, 0, source); - } - - // Move visible columns to the front of the list. - moveVisibleToFront() { - let newCols = this.displayColumns(); - this.columns.forEach(col => { if (!col.visible) newCols.push(col) }); - this.columns = newCols; - } - - moveColumn(col: EgGridColumn, diff: number) { - var srcIdx, targetIdx; - - this.columns.forEach((c, i) => { - if (c.name == col.name) srcIdx = i - }); - - targetIdx = srcIdx + diff; - if (targetIdx < 0) { - targetIdx = 0; - } else if (targetIdx >= this.columns.length) { - // Target index follows the last visible column. - var lastVisible = 0; - this.columns.forEach((c, idx) => { - if (c.visible) lastVisible = idx; - }); - - // When moving a column (down) causes one or more - // visible columns to shuffle forward, our column - // moves into the slot of the last visible column. - // Otherwise, put it into the slot directly following - // the last visible column. - targetIdx = srcIdx <= lastVisible ? lastVisible : lastVisible + 1; - } - - // Splice column out of old position, insert at new position. - this.columns.splice(srcIdx, 1); - this.columns.splice(targetIdx, 0, col); - } - - compileSaveObject(): EgGridColumnPersistConf[] { - // only store information about visible columns. - let conf = this.displayColumns(); - - // scrunch the data down to just the needed info - return conf.map(col => { - let c: EgGridColumnPersistConf = {name : col.name}; - if (col.align != 'left') c.align = col.align; - if (col.flex != 2) c.flex = col.flex; - if (Number(col.sort)) c.sort = Number(c.sort); - return c; - }); - } - - applyColumnSettings(conf: EgGridColumnPersistConf[]) { - if (!conf || conf.length == 0) return; - - let newCols = []; - - conf.forEach(colConf => { - let col = this.getColByName(colConf.name); - if (!col) return; // no such column in this grid. - - col.visible = true; - if (colConf.align) col.align = colConf.align; - if (colConf.flex) col.flex = colConf.flex; - if (colConf.sort) col.sort = colConf.sort; - - // Add to new columns array, avoid dupes. - if (newCols.filter(c => c.name == col.name).length == 0) - newCols.push(col); - }); - - // columns which are not expressed within the saved - // configuration are marked as non-visible and - // appended to the end of the new list of columns. - this.columns.forEach(c => { - if (conf.filter(cf => cf.name == c.name).length == 0) { - c.visible = false; - newCols.push(c); - } - }); - - this.columns = newCols; - } -} // Actions apply to specific rows export class EgGridToolbarAction { @@ -515,57 +589,12 @@ export class EgGridToolbarButton { action: () => any; } -export class EgGridRowSelector { - indexes: {[string:string] : boolean}; - - constructor() { - this.clear(); - } - - // Returns true if all of the requested indexes exist in the selector. - contains(index: string | string[]): boolean { - let indexes = [].concat(index); - for (let i = 0; i < indexes.length; i++) { // early exit - if (!this.indexes[indexes[i]]) - return false; - } - return true; - } - - select(index: string | string[]) { - let indexes = [].concat(index); - indexes.forEach(i => this.indexes[i] = true); - } - - deselect(index: string | string[]) { - let indexes = [].concat(index); - indexes.forEach(i => delete this.indexes[i]); - } - - // Returns the list of selected index values. - // in some contexts (template checkboxes) the value for an index is - // set to false to deselect instead of having it removed (via deselect()). - selected() { - return Object.keys(this.indexes).filter( - ind => {return Boolean(this.indexes[ind])}) - } - - isEmpty(): boolean { - return this.selected().length == 0; - } - - clear() { - this.indexes = {}; - } -} - export class EgGridDataSource { data: any[]; sort: any[]; allRowsRetrieved: boolean; getRows: (pager: Pager, sort: any[]) => Observable; - indexedRows: {[index:string] : any}; constructor() { this.sort = []; @@ -590,7 +619,7 @@ export class EgGridDataSource { requestPage(pager: Pager): Promise { if ( - this.getPageOfRows(pager).length == pager.limit + this.getPageOfRows(pager).length === pager.limit // already have all data || this.allRowsRetrieved // have no way to get more data. @@ -617,9 +646,9 @@ export class EgGridDataSource { // See if the last getRows() call resulted in the final set of data. checkAllRetrieved(pager: Pager, idx: number) { - if (this.allRowsRetrieved) return; + if (this.allRowsRetrieved) { return; } - if (idx == 0 || idx < (pager.limit + pager.offset)) { + if (idx === 0 || idx < (pager.limit + pager.offset)) { // last query returned nothing or less than one page. // confirm we have all of the preceding pages. if (!this.data.includes(undefined)) { -- 2.11.0