LP1835982 Grid cell text generator API migration user/blake/lp1835982-grid-csv-template-fields-2
authorblake <blake@mobiusconsortium.org>
Mon, 18 Nov 2019 16:00:57 +0000 (10:00 -0600)
committerblake <blake@mobiusconsortium.org>
Mon, 18 Nov 2019 16:00:57 +0000 (10:00 -0600)
Merge conflict resolution

Signed-off-by: blake <blake@mobiusconsortium.org>
15 files changed:
Open-ILS/src/eg2/src/app/share/grid/grid-column.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid.ts
Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set-list.component.html
Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set-list.component.ts
Open-ILS/src/eg2/src/app/staff/cat/vandelay/queue.component.html
Open-ILS/src/eg2/src/app/staff/cat/vandelay/queue.component.ts
Open-ILS/src/eg2/src/app/staff/cat/vandelay/queued-record-matches.component.html
Open-ILS/src/eg2/src/app/staff/cat/vandelay/queued-record-matches.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/record/copies.component.html
Open-ILS/src/eg2/src/app/staff/catalog/record/copies.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.html
Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts
Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.html
Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts

index c612eb4..bb30842 100644 (file)
@@ -39,6 +39,7 @@ export class GridColumnComponent implements OnInit {
     // Used in conjunction with cellTemplate
     @Input() cellContext: any;
     @Input() cellTemplate: TemplateRef<any>;
+    @Input() cellPrintValue: (row: any, cell: GridColumn) => string;
 
     @Input() disableTooltip: boolean;
 
@@ -60,6 +61,7 @@ export class GridColumnComponent implements OnInit {
         col.hidden = this.hidden === true;
         col.isIndex = this.index === true;
         col.cellTemplate = this.cellTemplate;
+        col.cellPrintValue = this.cellPrintValue;
         col.cellContext = this.cellContext;
         col.disableTooltip = this.disableTooltip;
         col.isSortable = this.sortable;
@@ -71,6 +73,12 @@ export class GridColumnComponent implements OnInit {
         col.timezoneContextOrg = this.timezoneContextOrg;
         col.isAuto = false;
         this.grid.context.columnSet.add(col);
+
+        if (this.cellTemplate &&
+            !this.grid.context.columnHasTextGenerator(col)) {
+            console.warn(
+                'No cellTextGenerator provided for "' + col.name + '"');
+        }
     }
 }
 
index 0d2321f..490cd9f 100644 (file)
@@ -4,7 +4,8 @@ import {IdlService} from '@eg/core/idl.service';
 import {OrgService} from '@eg/core/org.service';
 import {ServerStoreService} from '@eg/core/server-store.service';
 import {FormatService} from '@eg/core/format.service';
-import {GridContext, GridColumn, GridDataSource, GridRowFlairEntry} from './grid';
+import {GridContext, GridColumn, GridDataSource,
+    GridCellTextGenerator, GridRowFlairEntry} from './grid';
 import {GridToolbarComponent} from './grid-toolbar.component';
 
 /**
@@ -119,6 +120,8 @@ export class GridComponent implements OnInit, AfterViewInit, OnDestroy {
     // would go out of view
     @Input() stickyHeader: boolean;
 
+    @Input() cellTextGenerator: GridCellTextGenerator;
+
     context: GridContext;
 
     // These events are emitted from our grid-body component.
@@ -161,6 +164,8 @@ export class GridComponent implements OnInit, AfterViewInit, OnDestroy {
         this.context.showDeclaredFieldsOnly = this.showDeclaredFieldsOnly;
         this.context.rowFlairCallback = this.rowFlairCallback;
         this.context.disablePaging = this.disablePaging === true;
+        this.context.cellTextGenerator = this.cellTextGenerator;
+
         if (this.showFields) {
             this.context.defaultVisibleFields = this.showFields.split(',');
         }
index 01b5c09..fade713 100644 (file)
@@ -30,6 +30,11 @@ export class GridColumn {
     ternaryBool: boolean;
     timezoneContextOrg: number;
     cellTemplate: TemplateRef<any>;
+
+    // Provide a way for cells that are generated via cellTemplate's
+    // to provide an alternate text value suitable for printing.
+    cellPrintValue: (row: any, cell: GridColumn) => string;
+
     cellContext: any;
     isIndex: boolean;
     isDragTarget: boolean;
@@ -385,6 +390,13 @@ export class GridColumnSet {
     }
 }
 
+// Maps colunm names to functions which return plain text values for
+// each mapped column on a given row.  This is primarily useful for
+// generating print-friendly content for grid cells rendered via
+// cellTemplate.
+export interface GridCellTextGenerator {
+    [columnName: string]: (row: any) => string;
+}
 
 export class GridRowSelector {
     indexes: {[string: string]: boolean};
@@ -482,6 +494,7 @@ export class GridContext {
     showLinkSelectors: boolean;
     disablePaging: boolean;
     showDeclaredFieldsOnly: boolean;
+    cellTextGenerator: GridCellTextGenerator;
 
     // Allow calling code to know when the select-all-rows-in-page
     // action has occurred.
@@ -797,11 +810,14 @@ export class GridContext {
 
 
     getColumnTextContent(row: any, col: GridColumn): string {
-        if (col.cellTemplate) {
-            // TODO
-            // Extract the text content from the rendered template.
+        if (this.columnHasTextGenerator(col)) {
+            return this.cellTextGenerator[col.name](row);
         } else {
-            return this.getRowColumnValue(row, col);
+            if (col.cellTemplate) {
+                return ''; // avoid 'undefined' values
+            } else {
+                return this.getRowColumnValue(row, col);
+            }
         }
     }
 
@@ -1091,6 +1107,10 @@ export class GridContext {
         if (!persistKey) { return Promise.resolve(null); }
         return this.store.getItem('eg.grid.' + persistKey);
     }
+
+    columnHasTextGenerator(col: GridColumn): boolean {
+        return this.cellTextGenerator && col.name in this.cellTextGenerator;
+    }
 }
 
 
index 26c1ca0..67c9588 100644 (file)
@@ -19,7 +19,7 @@
   </a> 
 </ng-template>
 
-<eg-grid #grid [dataSource]="gridSource"
+<eg-grid #grid [dataSource]="gridSource" [cellTextGenerator]="cellTextGenerator"
   persistKey="cat.vandelay.match_set.list"
   idlClass="vms" [dataSource]="queueSource">
   <eg-grid-toolbar-button label="New Match Set" i18n-label [action]="createNew">
index 5f49fc1..7ea2ae8 100644 (file)
@@ -6,7 +6,7 @@ import {PcrudService} from '@eg/core/pcrud.service';
 import {OrgService} from '@eg/core/org.service';
 import {AuthService} from '@eg/core/auth.service';
 import {GridComponent} from '@eg/share/grid/grid.component';
-import {GridDataSource, GridColumn} from '@eg/share/grid/grid';
+import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
 
 @Component({
@@ -21,6 +21,8 @@ export class MatchSetListComponent implements AfterViewInit {
     @ViewChild('grid', { static: true }) grid: GridComponent;
     @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
 
+    cellTextGenerator: GridCellTextGenerator;
+
     constructor(
         private router: Router,
         private pcrud: PcrudService,
@@ -39,6 +41,10 @@ export class MatchSetListComponent implements AfterViewInit {
             });
         };
 
+        this.cellTextGenerator = {
+            name: row => row.name()
+        };
+
         this.createNew = () => {
             this.editDialog.mode = 'create';
             this.editDialog.open({size: 'lg'})
index 2c1b3c3..16c97da 100644 (file)
@@ -130,7 +130,7 @@ because there are a lot of them.
 <eg-grid #queueGrid [dataSource]="queueSource"
   persistKey="cat.vandelay.queue.{{queueType}}"
   (onRowActivate)="openRecord($event)"
-  [pageOffset]="queuePageOffset()"
+  [pageOffset]="queuePageOffset()" [cellTextGenerator]="cellTextGenerator"
   hideFields="language,pagination,price,rec_identifier,eg_tcn_source,eg_identifier,item_barcode,zsource">
 
   <eg-grid-toolbar-checkbox i18n-label label="Records With Matches"
@@ -143,13 +143,14 @@ because there are a lot of them.
     (onChange)="limitToImportErrors($event)"></eg-grid-toolbar-checkbox>
 
   <eg-grid-column name="id" [index]="true" [hidden]="true"></eg-grid-column>
-  <eg-grid-column i18n-label label="Matches"
-    name="+matches" [cellTemplate]="matchesTmpl"></eg-grid-column>
+  <eg-grid-column i18n-label label="Matches" name="+matches" 
+    [cellTemplate]="matchesTmpl" [cellPrintValue]="cellPrintValues"></eg-grid-column>
   <eg-grid-column name="import_error" i18n-label
-    label="Import Errors" [cellTemplate]="errorsTmpl"></eg-grid-column>
+    label="Import Errors" [cellTemplate]="errorsTmpl" 
+      [cellPrintValue]="cellPrintValues"></eg-grid-column>
   <eg-grid-column name="import_time" i18n-label
     label="Import Date" datatype="timestamp"></eg-grid-column>
-  <eg-grid-column name="imported_as" i18n-label
-    label="Imported As" [cellTemplate]="importedAsTmpl"></eg-grid-column>
+  <eg-grid-column name="imported_as" i18n-label label="Imported As" 
+    [cellTemplate]="importedAsTmpl" [cellPrintValue]="cellPrintValues"></eg-grid-column>
 </eg-grid>
 
index 6e6fca2..02d0034 100644 (file)
@@ -10,7 +10,7 @@ import {AuthService} from '@eg/core/auth.service';
 import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
 import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
 import {GridComponent} from '@eg/share/grid/grid.component';
-import {GridDataSource, GridColumn} from '@eg/share/grid/grid';
+import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
 import {VandelayService, VandelayImportSelection,
     VANDELAY_EXPORT_PATH} from './vandelay.service';
 
@@ -38,6 +38,8 @@ export class QueueComponent implements OnInit, AfterViewInit {
     @ViewChild('confirmDelDlg', { static: false }) confirmDelDlg: ConfirmDialogComponent;
     @ViewChild('progressDlg', { static: true }) progressDlg: ProgressDialogComponent;
 
+    cellTextGenerator: GridCellTextGenerator;
+
     constructor(
         private router: Router,
         private route: ActivatedRoute,
@@ -57,6 +59,11 @@ export class QueueComponent implements OnInit, AfterViewInit {
             return this.loadQueueRecords(pager);
         };
 
+        this.cellTextGenerator = {
+            '+matches': row => row.matches.length + '',
+            'import_error': row => row.import_error,
+            'imported_as': row => row.imported_as + ''
+        };
     }
 
     ngOnInit() {
index 679f716..f149cc8 100644 (file)
@@ -15,7 +15,7 @@
 <ng-container *ngIf="queueType == 'bib'">
   <eg-grid #bibGrid [dataSource]="bibDataSource" 
     (onRowClick)="matchRowClick($event)"
-    [disableSelect]="true" [disableMultiSelect]="true">
+    [disableSelect]="true" [disableMultiSelect]="true" [cellTextGenerator]="cellTextGenerator">
     <!--
     <eg-grid-toolbar-action i18n-label label="Mark As Overlay Target"
       [action]="markOverlayTarget">
index a4ac067..dfbee69 100644 (file)
@@ -4,7 +4,7 @@ import {Observable, of} from 'rxjs';
 import {map} from 'rxjs/operators';
 import {Pager} from '@eg/share/util/pager';
 import {GridComponent} from '@eg/share/grid/grid.component';
-import {GridDataSource, GridColumn} from '@eg/share/grid/grid';
+import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
 import {IdlObject} from '@eg/core/idl.service';
 import {EventService} from '@eg/core/event.service';
 import {NetService} from '@eg/core/net.service';
@@ -31,6 +31,8 @@ export class QueuedRecordMatchesComponent implements OnInit {
     matchRowClick: (row: any) => void;
     matchMap: {[id: number]: IdlObject};
 
+    cellTextGenerator: GridCellTextGenerator;
+
     constructor(
         private router: Router,
         private route: ActivatedRoute,
@@ -48,6 +50,12 @@ export class QueuedRecordMatchesComponent implements OnInit {
             return this.getBibMatchRows(pager);
         };
 
+        this.cellTextGenerator = {
+            selected: row => this.isOverlayTarget(row.id) + '',
+            eg_record: row => row.eg_record + ''
+        };
+
+
         /* TODO
         this.authDataSource.getRows = (pager: Pager) => {
         }
index 7ee041f..2d6707b 100644 (file)
 
 <div class='eg-copies w-100 mt-3'>
   <eg-grid #copyGrid [dataSource]="gridDataSource" 
-    [disableSelect]="true"
+    [disableSelect]="true" [cellTextGenerator]="cellTextGenerator"
     [sortable]="false" persistKey="catalog.record.copies">
     <eg-grid-column i18n-label label="Item ID" path="id" 
       [hidden]="true" [index]="true">
     </eg-grid-column>
     <eg-grid-column i18n-label label="Location" path="circ_lib" datatype="org_unit">
     </eg-grid-column>
-    <eg-grid-column i18n-label label="Call Number / Item Notes" 
-      name="callnumber" [cellTemplate]="cnTemplate">
+    <eg-grid-column i18n-label label="Call Number / Item Notes" name="callnumber" 
+      [cellTemplate]="cnTemplate">
     </eg-grid-column>
     <eg-grid-column i18n-label label="Barcode" name="barcode"
       [cellTemplate]="barcodeTemplate">
@@ -60,7 +60,8 @@
       path="active_date" datatype="timestamp">
     </eg-grid-column>
     <eg-grid-column i18n-label label="Holdable?" name="holdable" 
-      [cellTemplate]="holdableTemplate" [cellContext]="copyContext">
+      [cellTemplate]="holdableTemplate" [cellContext]="copyContext" 
+      [cellPrintValue]="cellPrintValues">
     </eg-grid-column>
     <eg-grid-column i18n-label label="Status" path="copy_status">
     </eg-grid-column>
index 24350d8..b713fd6 100644 (file)
@@ -5,7 +5,7 @@ import {NetService} from '@eg/core/net.service';
 import {StaffCatalogService} from '../catalog.service';
 import {Pager} from '@eg/share/util/pager';
 import {OrgService} from '@eg/core/org.service';
-import {GridDataSource} from '@eg/share/grid/grid';
+import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
 import {GridComponent} from '@eg/share/grid/grid.component';
 
 @Component({
@@ -29,6 +29,8 @@ export class CopiesComponent implements OnInit {
         }
     }
 
+    cellTextGenerator: GridCellTextGenerator;
+
     constructor(
         private net: NetService,
         private org: OrgService,
@@ -52,6 +54,13 @@ export class CopiesComponent implements OnInit {
                     && copy.status_holdable === 't';
             }
         };
+
+        this.cellTextGenerator = {
+            callnumber: row => `${row.call_number_prefix_label} ` +
+                `${row.call_number_label} ${row.call_number_suffix_label}`,
+            holdable: row => this.copyContext.holdable(row),
+            barcode: row => row.barcode
+        };
     }
 
     collectData() {
index bcd980e..bb1606c 100644 (file)
@@ -57,7 +57,7 @@
 <div class='eg-copies w-100 mt-3'>
   <eg-grid #holdingsGrid [dataSource]="gridDataSource"
     (onRowActivate)="onRowActivate($event)" [disablePaging]="true"
-    [rowClassCallback]="rowClassCallback"
+    [rowClassCallback]="rowClassCallback" [cellTextGenerator]="cellTextGenerator"
     [sortable]="false" persistKey="cat.holdings">
 
     <!-- checkboxes / filters -->
index 1c78e59..4186b7a 100644 (file)
@@ -9,7 +9,7 @@ import {StaffCatalogService} from '../catalog.service';
 import {OrgService} from '@eg/core/org.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {AuthService} from '@eg/core/auth.service';
-import {GridDataSource} from '@eg/share/grid/grid';
+import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
 import {GridComponent} from '@eg/share/grid/grid.component';
 import {GridToolbarCheckboxComponent
     } from '@eg/share/grid/grid-toolbar-checkbox.component';
@@ -131,6 +131,7 @@ export class HoldingsMaintenanceComponent implements OnInit {
     renderFromPrefs: boolean;
 
     rowClassCallback: (row: any) => string;
+    cellTextGenerator: GridCellTextGenerator;
 
     private _recId: number;
     @Input() set recordId(id: number) {
@@ -182,6 +183,13 @@ export class HoldingsMaintenanceComponent implements OnInit {
             }
         };
 
+        // Text-ify function for cells that use display templates.
+        this.cellTextGenerator = {
+            owner_label: row => row.locationLabel,
+            holdable: row => row.copy ?
+                this.gridTemplateContext.copyIsHoldable(row.copy) : ''
+        };
+
         this.gridTemplateContext = {
             toggleExpandRow: (row: HoldingsEntry) => {
                 row.treeNode.expanded = !row.treeNode.expanded;
index 14f96e5..b3c7705 100644 (file)
@@ -31,7 +31,7 @@
     </div>
 
     <eg-grid #holdsGrid [dataSource]="gridDataSource" [sortable]="true"
-      [useLocalSort]="enablePreFetch"
+      [useLocalSort]="enablePreFetch" [cellTextGenerator]="cellTextGenerator"
       [multiSortable]="true" [persistKey]="persistKey"
       (onRowActivate)="showDetail($event)">
 
           {{hold.title}}
         </a>
       </ng-template>
-      <eg-grid-column i18n-label label="Title" [hidden]="true"
-          name='title' [cellTemplate]="titleTmpl"></eg-grid-column>
+      <eg-grid-column i18n-label label="Title" [hidden]="true" name='title' 
+        [cellTemplate]="titleTmpl"></eg-grid-column>
       <eg-grid-column i18n-label label="Author" path='author'
           [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Potential Items" path='potentials' datatype="int">
index 1cc352f..029883b 100644 (file)
@@ -6,7 +6,7 @@ import {OrgService} from '@eg/core/org.service';
 import {AuthService} from '@eg/core/auth.service';
 import {Pager} from '@eg/share/util/pager';
 import {ServerStoreService} from '@eg/core/server-store.service';
-import {GridDataSource} from '@eg/share/grid/grid';
+import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
 import {GridComponent} from '@eg/share/grid/grid.component';
 import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
 import {MarkDamagedDialogComponent
@@ -111,6 +111,8 @@ export class HoldsGridComponent implements OnInit {
         }
     }
 
+    cellTextGenerator: GridCellTextGenerator;
+
     constructor(
         private net: NetService,
         private org: OrgService,
@@ -142,6 +144,12 @@ export class HoldsGridComponent implements OnInit {
             sort = sort.length > 0 ? sort : this.defaultSort;
             return this.fetchHolds(pager, sort);
         };
+
+        // Text-ify function for cells that use display templates.
+        this.cellTextGenerator = {
+            title: row => row.title,
+            cp_barcode: row => row.cp_barcode
+        };
     }
 
     // Returns true after all data/settings/etc required to render the