LP#1775466 More formatting / dates
authorBill Erickson <berickxx@gmail.com>
Sat, 12 May 2018 16:32:22 +0000 (12:32 -0400)
committerBill Erickson <berickxx@gmail.com>
Wed, 6 Jun 2018 20:59:26 +0000 (16:59 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/common.module.ts
Open-ILS/src/eg2/src/app/share/grid/grid-column.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid.service.ts
Open-ILS/src/eg2/src/app/share/util/format.service.ts [new file with mode: 0644]

index 8cc94c7..5f5f97f 100644 (file)
@@ -1,11 +1,12 @@
 /**
  * Modules, services, and components used by all apps.
  */ 
-import {CommonModule} from '@angular/common';
+import {CommonModule, DatePipe, CurrencyPipe} from '@angular/common';
 import {NgModule, ModuleWithProviders} from '@angular/core';
 import {FormsModule} from '@angular/forms';
 import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
 
+
 import {EgEventService} from '@eg/core/event.service';
 import {EgStoreService} from '@eg/core/store.service';
 import {EgIdlService} from '@eg/core/idl.service';
@@ -15,6 +16,7 @@ import {EgPermService} from '@eg/core/perm.service';
 import {EgPcrudService} from '@eg/core/pcrud.service';
 import {EgOrgService} from '@eg/core/org.service';
 import {EgAudioService} from '@eg/share/util/audio.service';
+import {EgFormatService} from '@eg/share/util/format.service';
 
 @NgModule({
   declarations: [
@@ -38,6 +40,8 @@ export class EgCommonModule {
         return {
             ngModule: EgCommonModule,
             providers: [
+                DatePipe,
+                CurrencyPipe,
                 EgEventService,
                 EgStoreService,
                 EgIdlService,
@@ -46,7 +50,8 @@ export class EgCommonModule {
                 EgPermService,
                 EgPcrudService,
                 EgOrgService,
-                EgAudioService
+                EgAudioService,
+                EgFormatService
             ]
         };
     }
index a89c46e..1f2b49e 100644 (file)
@@ -19,6 +19,7 @@ export class EgGridColumnComponent implements OnInit {
     @Input() visible: boolean;
     @Input() hidden: boolean;
     @Input() sortable: boolean;
+    @Input() datatype: string;
     @Input() multiSortable: boolean;
     @Input() cellTemplate: TemplateRef<any>;
 
index 17703f3..196f510 100644 (file)
@@ -3,6 +3,7 @@ import {EgIdlService, EgIdlObject} from '@eg/core/idl.service';
 import {EgOrgService} from '@eg/core/org.service';
 import {EgPcrudService} from '@eg/core/pcrud.service';
 import {EgStoreService} from '@eg/core/store.service';
+import {EgFormatService} from '@eg/share/util/format.service';
 
 
 @Injectable()
@@ -12,7 +13,8 @@ export class EgGridService {
         private idl: EgIdlService,
         private org: EgOrgService,
         private store: EgStoreService,
-        private pcrud: EgPcrudService
+        private pcrud: EgPcrudService,
+        private format: EgFormatService
     ) {
     }
 
@@ -23,31 +25,13 @@ export class EgGridService {
     }
 
     getRowColumnValue(row: any, col: EgGridColumn): string {
-        if (row[col.name] === undefined || row[col.name] === null) 
-            return '';
-
-        if (col.idlFieldDef) 
-            return this.getRowColumnIdlValue(row, col);
-
+        let val;
         if (typeof row[col.name] == 'function') {
-            let val = row[col.name]();
-            if (val === undefined || val === null) return '';
-            return val+'';
-        }
-
-        return row[col.name]+'';
-    }
-
-    getRowColumnIdlValue(row: any, col: EgGridColumn): string {
-        let val = row[col.name]();
-        if (val === undefined || val === null) return '';
-
-        if (col.idlFieldDef.datatype == 'org_unit') {
-            let o = this.org.get(val);
-            if (o) return o.shortname(); 
+            val = row[col.name]();
+        } else {
+            val = row[col.name]
         }
-            
-        return val+'';
+        return this.format.transform({value: val, datatype: col.datatype});
     }
 
     generateColumns(columnSet: EgGridColumnSet) {
@@ -60,6 +44,7 @@ export class EgGridService {
                 col.name = field.name;
                 col.label = field.label || field.name;
                 col.idlFieldDef = field;
+                col.datatype = field.datatype;
                 if (field.name == this.idl.classes[columnSet.idlClass].pkey)
                     col.isIndex = true;
                 columnSet.add(col);
@@ -99,6 +84,7 @@ export class EgGridColumn {
     sort: number;
     idlClass: string;
     idlFieldDef: any;
+    datatype: string;
     cellTemplate: TemplateRef<any>;
     isIndex: boolean;
     isDragTarget: boolean;
@@ -135,6 +121,7 @@ export class EgGridColumnSet {
         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;
 
@@ -295,9 +282,8 @@ export class EgGridRowSelector {
     // Returns true if all of the requested indexes exist in the selector.
     contains(index: string | string[]): boolean {
         let indexes = [].concat(index);
-        let selected = Object.keys(this.indexes);
         for (let i = 0; i < indexes.length; i++) { // early exit
-            if (!selected.includes(indexes[i]))
+            if (!this.indexes[indexes[i]])
                 return false; 
         }
         return true;
@@ -313,8 +299,12 @@ export class EgGridRowSelector {
         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);
+        return Object.keys(this.indexes).filter(
+            ind => {return Boolean(this.indexes[ind])})
     }
 
     isEmpty(): boolean {
diff --git a/Open-ILS/src/eg2/src/app/share/util/format.service.ts b/Open-ILS/src/eg2/src/app/share/util/format.service.ts
new file mode 100644 (file)
index 0000000..551984a
--- /dev/null
@@ -0,0 +1,67 @@
+import {Injectable} from '@angular/core';
+import {DatePipe, CurrencyPipe} from '@angular/common';
+import {EgIdlService, EgIdlObject} from '@eg/core/idl.service';
+import {EgOrgService} from '@eg/core/org.service';
+
+export interface EgFormatParams {
+    value: any;
+    idlClass?: string;
+    idlField?: string;
+    datatype?: string;
+    orgField?: string; // 'shortname' || 'name'
+}
+
+@Injectable()
+export class EgFormatService {
+
+    constructor(
+        private datePipe: DatePipe,
+        private currencyPipe: CurrencyPipe,
+        private idl: EgIdlService,
+        private org: EgOrgService
+    ) {}
+
+    /**
+     * Create a human-friendly display version of any field type.
+     */
+    transform(params: EgFormatParams): string {
+        let value = params.value;
+
+        if (   value === undefined 
+            || value === null 
+            || value === '' 
+            || Number.isNaN(value)) return '';
+
+        let datatype = params.datatype;
+
+        if (!datatype) {
+            if (params.idlClass && params.idlField) {
+                datatype = this.idl.classes[params.idlClass]
+                    .field_map[params.idlField].datatype;
+            } else {
+                // Assume it's a primitive value
+                return value + '';
+            }
+        }
+
+        switch(datatype) {
+
+            case 'org_unit':
+                let orgField = params.orgField || 'shortname';
+                let org = this.org.get(value);
+                return org ? org[orgField]() : '';
+
+            case 'timestamp':
+                let date = new Date(value);
+                // TODO: date format settings and options.
+                return this.datePipe.transform(date, 'yyyy-MM-dd');
+
+            case 'money':
+                return this.currencyPipe.transform(value);
+
+            default:
+                return value + '';
+        }
+    }
+}
+