LP#1779158 Merge target selection improvements
authorBill Erickson <berickxx@gmail.com>
Thu, 12 Jul 2018 15:05:01 +0000 (11:05 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 11 Oct 2018 18:56:30 +0000 (14:56 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/staff/cat/vandelay/queue-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/cat/vandelay/vandelay.service.ts

index 84c73a3..888c8a5 100644 (file)
@@ -36,6 +36,9 @@ export class QueueListComponent {
         this.queueType = 'bib';
         this.queueSource = new GridDataSource();
 
+        // Reset queue grid offset
+        this.vandelay.queuePageOffset = 0;
+
         // queue API does not support sorting
         this.queueSource.getRows = (pager: Pager) => {
             return this.loadQueues(pager);
index dab90bc..6136b13 100644 (file)
@@ -119,6 +119,7 @@ because there are a lot of them.
 <eg-grid #queueGrid [dataSource]="queueSource"
   persistKey="cat.vandelay.queue.{{queueType}}"
   (onRowActivate)="openRecord($event)"
+  [pageOffset]="queuePageOffset()"
   hideFields="language,pagination,price,rec_identifier,eg_tcn_source,eg_identifier,item_barcode,zsource">
 
   <eg-grid-toolbar-checkbox i18n-label label="Records With Matches"
index 4d34b84..9d0ccb1 100644 (file)
@@ -59,6 +59,7 @@ export class QueueComponent implements OnInit, AfterViewInit {
 
         this.queueSource = new GridDataSource();
         this.queueSource.getRows = (pager: Pager) => {
+            this.vandelay.queuePageOffset = pager.offset;
             return this.loadQueueRecords(pager);
         };
 
@@ -81,6 +82,10 @@ export class QueueComponent implements OnInit, AfterViewInit {
     ngOnInit() {
     }
 
+    queuePageOffset(): number {
+        return this.vandelay.queuePageOffset;
+    }
+
     ngAfterViewInit() {
         if (this.queueType) { 
             this.applyQueueType(); 
index b6215d4..db72a9a 100644 (file)
@@ -5,17 +5,28 @@
   </a>
 </ng-template>
 
+<ng-template #targetTemplate let-row="row">
+  <ng-container *ngIf="isOverlayTarget(row.id)">
+    <span i18n-title title="Selected Merge Target" 
+      class="material-icons">check_circle</span>
+  </ng-container>
+</ng-template>
+
 <ng-container *ngIf="queueType == 'bib'">
   <eg-grid #bibGrid [dataSource]="bibDataSource" 
-    [rowFlairIsEnabled]="true"                                                   
-    [rowFlairCallback]="matchRowCallback"
+    (onRowClick)="matchRowClick($event)"
     [disableMultiSelect]="true">
+    <!--
     <eg-grid-toolbar-action i18n-label label="Mark As Overlay Target"
       [action]="markOverlayTarget">
     </eg-grid-toolbar-action>
+    -->
     <eg-grid-column name="id" [index]="true" [hidden]="true" 
       i18n-label label="Match ID">
     </eg-grid-column>
+    <eg-grid-column name="selected" i18n-label label="Merge Target"
+      [cellTemplate]="targetTemplate">
+    </eg-grid-column>
     <eg-grid-column name="eg_record" i18n-label label="Record ID"
       [cellTemplate]="bibIdTemplate">
     </eg-grid-column>
index 32e7917..74e70f1 100644 (file)
@@ -5,7 +5,7 @@ import 'rxjs/add/observable/of';
 import {map} from 'rxjs/operators/map';
 import {Pager} from '@eg/share/util/pager';
 import {GridComponent} from '@eg/share/grid/grid.component';
-import {GridDataSource, GridColumn, GridRowFlairEntry} from '@eg/share/grid/grid';
+import {GridDataSource, GridColumn} 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';
@@ -29,7 +29,8 @@ export class QueuedRecordMatchesComponent implements OnInit {
     bibDataSource: GridDataSource;
     authDataSource: GridDataSource;
     markOverlayTarget: (rows: any[]) => any;
-    matchRowCallback: (row: any) => GridRowFlairEntry;
+    matchRowClick: (row: any) => void;
+    matchMap: {[id: number]: IdlObject};
 
     constructor(
         private router: Router,
@@ -53,36 +54,41 @@ export class QueuedRecordMatchesComponent implements OnInit {
         }
         */
 
-        this.markOverlayTarget = (rows: any[]) => {
+        // Mark or un-mark as row as the merge target on row click
+        this.matchRowClick = (row: any) => {
+            this.toggleMergeTarget(row.id);
+        }
+    }
+
+    toggleMergeTarget(matchId: number) {
+
+        if (this.isOverlayTarget(matchId)) {
+
+            // clear selection on secondary click;
+            delete this.vandelay.importSelection.overlayMap[this.recordId];
+
+        } else {
+            // Add to selection.
+            // Start a new one if necessary, which will be adopted
+            // and completed by the queue UI before import.
 
-            // Start a new import selection object if needed.
-            // This will be adopted by the queue UI before import.
             let selection = this.vandelay.importSelection;
             if (!selection) {
                 selection = new VandelayImportSelection();
                 this.vandelay.importSelection = selection;
             }
-
-            // Grid is configured for single-row-select.
-            const match = rows[0];
-            selection.overlayMap[this.recordId] = match.eg_record;
-        }
-
-        this.matchRowCallback = (row: any) => {
-            const selection = this.vandelay.importSelection;
-            if (selection) {
-                const target = selection.overlayMap[this.recordId];
-                if (target === row.eg_record) {
-                    return {icon: 'check_circle'};
-                }
-            }
-            return null;
+            const match = this.matchMap[matchId];
+            selection.overlayMap[this.recordId] = match.eg_record();
         }
     }
 
-    hasOverlayTarget(rid: number): boolean {
-        return this.vandelay.importSelection &&
-            Boolean(this.vandelay.importSelection.overlayMap[rid]);
+    isOverlayTarget(matchId: number): boolean {
+        const selection = this.vandelay.importSelection;
+        if (selection) {
+            const match = this.matchMap[matchId];
+            return selection.overlayMap[this.recordId] === match.eg_record();
+        }
+        return false;
     }
 
     ngOnInit() {}
@@ -96,7 +102,9 @@ export class QueuedRecordMatchesComponent implements OnInit {
 
                 const matches = this.queuedRecord.matches();
                 const recIds = [];
+                this.matchMap = {};
                 matches.forEach(m => {
+                    this.matchMap[m.id()] = m;
                     if (!recIds.includes(m.eg_record())) {
                         recIds.push(m.eg_record());
                     }
index 178b2f0..375a841 100644 (file)
@@ -46,6 +46,11 @@ export class VandelayService {
     // the import page.  Fields managed externally.
     importSelection: VandelayImportSelection;
 
+    // Track the last grid offset in the queue page so we
+    // can return the user to the same page of data after
+    // going to the matches page.
+    queuePageOffset: number;
+
     constructor(
         private http: HttpClient,
         private idl: IdlService,
@@ -61,6 +66,7 @@ export class VandelayService {
         this.allQueues = {};
         this.matchSets = {};
         this.importSelection = null;
+        this.queuePageOffset = 0;
     }
 
     getAttrDefs(dtype: string): Promise<IdlObject[]> {