lp1811710: minor tweaks to the eg2 holds grid
authorJason Etheridge <jason@EquinoxInitiative.org>
Fri, 7 Jun 2019 14:30:53 +0000 (10:30 -0400)
committerChris Sharp <csharp@georgialibraries.org>
Tue, 15 Sep 2020 15:13:15 +0000 (11:13 -0400)
column label fixes and let some actions work with multiple rows

fix for item barcode link

prevent certain actions from spawning broken interfaces

disable Title Hold Transfer if non-title holds are selected

render hold status

return the sms carrier name instead of the id in the wide_holds API
(we may want to back this one out and do it differently)

show time component for timestamp columns

fixed live summaries for various hold actions intended for large batches

remove mvr.* from eg2 holds grid; not doing anything

Signed-off-by: Jason Etheridge <jason@EquinoxInitiative.org>
Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Signed-off-by: Terran McCanna <tmccanna@georgialibraries.org>
Signed-off-by: Chris Sharp <csharp@georgialibraries.org>

Open-ILS/src/eg2/src/app/staff/share/holdings/mark-missing-dialog.component.ts
Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.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
Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.ts
Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm

index f68d31f..079298e 100644 (file)
@@ -1,10 +1,11 @@
 import {Component, OnInit, Input, ViewChild} from '@angular/core';
+import {Observable, throwError} from 'rxjs';
 import {NetService} from '@eg/core/net.service';
 import {EventService} from '@eg/core/event.service';
 import {ToastService} from '@eg/share/toast/toast.service';
 import {AuthService} from '@eg/core/auth.service';
 import {DialogComponent} from '@eg/share/dialog/dialog.component';
-import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
+import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
 import {StringComponent} from '@eg/share/string/string.component';
 
 
@@ -42,6 +43,12 @@ export class MarkMissingDialogComponent
 
     ngOnInit() {}
 
+    open(args: NgbModalOptions): Observable<boolean> {
+        this.numSucceeded = 0;
+        this.numFailed = 0;
+        return super.open(args);
+    }
+
     async markOneItemMissing(ids: number[]): Promise<any> {
         if (ids.length === 0) {
             return Promise.resolve();
index 2320081..2d6d790 100644 (file)
@@ -51,6 +51,9 @@ export class HoldCancelDialogComponent
 
     open(args: NgbModalOptions): Observable<boolean> {
 
+        this.numSucceeded = 0;
+        this.numFailed = 0;
+
         if (this.cancelReasons.length === 0) {
             this.pcrud.retrieveAll('ahrcc', {}, {atomic: true}).toPromise()
             .then(reasons => {
index 850f097..ded8dcd 100644 (file)
@@ -9,6 +9,21 @@
 <eg-hold-cancel-dialog #cancelDialog></eg-hold-cancel-dialog>
 <eg-hold-manage-dialog #manageDialog></eg-hold-manage-dialog>
 
+<ng-template #statusTemplate let-hold="row">
+  <ng-container [ngSwitch]="hold.hold_status">
+    <div *ngSwitchCase="-1" i18n>Unknown Error</div>
+    <div *ngSwitchCase="1" i18n>Waiting for Item</div>
+    <div *ngSwitchCase="2" i18n>Waiting for Capture</div>
+    <div *ngSwitchCase="3" i18n>In Transit</div>
+    <div *ngSwitchCase="4" i18n>Ready for Pickup</div>
+    <div *ngSwitchCase="5" i18n>Hold Shelf Delay</div>
+    <div *ngSwitchCase="6" i18n>Canceled</div>
+    <div *ngSwitchCase="7" i18n>Suspended</div>
+    <div *ngSwitchCase="8" i18n>Wrong Shelf</div>
+    <div *ngSwitchCase="9" i18n>Fulfilled</div>
+  </ng-container>
+</ng-template>
+
 <div class='eg-holds w-100 mt-3'>
 
   <ng-container *ngIf="mode == 'detail'">
@@ -61,6 +76,7 @@
 
       <eg-grid-toolbar-action
         i18n-group group="Hold" i18n-label label="Transfer To Marked Title"
+        [disableOnRows]="nonTitleHoldsSelected"
         (onClick)="showTransferDialog($event)">
       </eg-grid-toolbar-action>
 
 
       <eg-grid-column i18n-label label="Patron alias" path="usr_alias"></eg-grid-column>
       <eg-grid-column i18n-label label="Request Date"
-        path='request_time' datatype="timestamp" [datePlusTime]="true">
-      </eg-grid-column>
+          path='request_time' datatype="timestamp" [datePlusTime]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Capture Date" path='capture_time'
-          datatype="timestamp"></eg-grid-column>
+          datatype="timestamp" [datePlusTime]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Available Date" path='shelf_time'
-          datatype="timestamp"></eg-grid-column>
+          datatype="timestamp" [datePlusTime]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Hold Type" path='hold_type'></eg-grid-column>
       <eg-grid-column i18n-label label="Pickup Library" path='pl_shortname'></eg-grid-column>
 
           [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Potential Items" path='potentials' datatype="int">
       </eg-grid-column>
-      <eg-grid-column i18n-label label="Status" path='status_string'>
+      <eg-grid-column i18n-label label="Status" [cellTemplate]="statusTemplate">
       </eg-grid-column>
       <eg-grid-column i18n-label label="Queue Position"
           path='relative_queue_position' [hidden]="true" datatype="int"></eg-grid-column>
 
       <eg-grid-column path='acnp_label' i18n-label label="CN Prefix" [hidden]="true"></eg-grid-column>
       <eg-grid-column path='acns_label' i18n-label label="CN Suffix" [hidden]="true"></eg-grid-column>
-      <eg-grid-column path='mvr.*' parent-idl-class="mvr" [hidden]="true"></eg-grid-column>
-
-      <eg-grid-column i18n-label label="Fulfillment Date/Time" path='fulfillment_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Checkin Time" path='checkin_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Return Time" path='return_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Last Targeting Date/Time" path='prev_check_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Expire Time" path='expire_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Hold Cancel Date/Time" path='cancel_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
+
+      <eg-grid-column i18n-label label="Fulfillment Date/Time" path='fulfillment_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Checkin Time" path='checkin_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Return Time" path='return_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Last Targeting Date/Time" path='prev_check_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Expire Time" path='expire_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Hold Cancel Date/Time" path='cancel_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Cancelation note" path='cancel_note' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Hold Target" path='target' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Current Item" path='current_copy' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Notify by Email?" path='email_notify' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="SMS Carrier" path='sms_carrier' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Currently Frozen" path='frozen' datatype="bool" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Activation Date" path='thaw_date' datatype="timestamp" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Activation Date" path='thaw_date' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Top of Queue" path='cut_in_line' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Is Mint Condition" path='mint_condition' datatype="bool" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Shelf Expire Time" path='shelf_expire_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Shelf Expire Time" path='shelf_expire_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Current Shelf Library" path='current_shelf_lib' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Behind Desk" path='behind_desk' datatype="bool" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Hopeless Date" path='hopeless_date' datatype="timestamp" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Status" path='hold_status' [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Hopeless Date" path='hopeless_date' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Clearable" path='clear_me' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Is Staff-placed Hold" path='is_staff_hold' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Cancelation Cause ID" path='cc_id' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Pickup Library Phone" path='pl_phone' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Pickup Library Opac Visible" path='pl_opac_visible' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Transit ID" path='tr_id' [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Transit Send Time" path='tr_source_send_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Transit Receive Time" path='tr_dest_recv_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Transit Send Time" path='tr_source_send_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Transit Receive Time" path='tr_dest_recv_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Transit Item" path='tr_target_copy' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Transit Source" path='tr_source' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Transit Destination" path='tr_dest' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Transit Item Status" path='tr_copy_status' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Transit Hold" path='tr_hold' [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Transit Cancel Time" path='tr_cancel_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Transit Cancel Time" path='tr_cancel_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Hold Note Count" path='note_count' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="User Display Name" path='usr_display_name' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Requestor Username" path='rusr_usrname' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Item Deleted" path='cp_deleted' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Floating Group" path='cp_floating' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Precat Dummy ISBN" path='cp_dummy_isbn' [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Item Status Change Time" path='cp_status_change_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Item Active Date" path='cp_active_date' datatype="timestamp" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Item Status Change Time" path='cp_status_change_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Item Active Date" path='cp_active_date' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Item Is Mint Condition" path='cp_mint_condition' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Cost" path='cp_cost' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Status Is Holdable" path='cs_holdable' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Status Is Item-Active" path='cs_copy_active' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Status Is Deleted" path='cs_restrict_copy_delete' datatype="bool" [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Status Is Available" path='cs_is_available' datatype="bool" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Issuance i18n-label label" path='issuance_label' [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Issuance label" path='issuance_label' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Call Number ID" path='cn_id' [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="CN i18n-label label" path='cn_label' [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="CN i18n-label label Class" path='cn_label_class' [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="CN label" path='cn_label' [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="CN label Class" path='cn_label_class' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="CN Sort Key" path='cn_label_sortkey' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Part ID" path='p_id' [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Part i18n-label label" path='p_label' [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Part label" path='p_label' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Part Sort Key" path='p_label_sortkey' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Part Is Deleted" path='p_deleted' datatype="bool" [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="CN Full i18n-label label" path='cn_full_label' [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="CN Full label" path='cn_full_label' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Record ID" path='record_id' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Item Location ID" path='acpl_id' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Item Location" path='acpl_name' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Peer Hold Count" path='other_holds' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Total Wait Time" path='total_wait_time' [hidden]="true"></eg-grid-column>
       <eg-grid-column i18n-label label="Notify Count" path='notification_count' [hidden]="true"></eg-grid-column>
-      <eg-grid-column i18n-label label="Last Notify Time" path='last_notification_time' datatype="timestamp" [hidden]="true"></eg-grid-column>
+      <eg-grid-column i18n-label label="Last Notify Time" path='last_notification_time' datatype="timestamp" [datePlusTime]="true" [hidden]="true"></eg-grid-column>
 
     </eg-grid>
 
index 5828243..c2e5b10 100644 (file)
@@ -330,6 +330,16 @@ export class HoldsGridComponent implements OnInit {
         return found;
     }
 
+    nonTitleHoldsSelected(rows: IdlObject[]) {
+        var found = false;
+        rows.forEach( row => {
+           if (row.hold_type != 'T') {
+             found = true;
+           }
+        });
+        return found;
+    }
+
     showDetails(rows: any[]) {
         this.showDetail(rows[0]);
     }
@@ -360,19 +370,21 @@ export class HoldsGridComponent implements OnInit {
 
 
     showRecentCircs(rows: any[]) {
-        if (rows.length) {
+        const copyIds = Array.from(new Set( rows.map(r => r.cp_id).filter( cp_id => Boolean(cp_id)) ));
+        copyIds.forEach( copyId => {
             const url =
-                '/eg/staff/cat/item/' + rows[0].cp_id + '/circ_list';
+                '/eg/staff/cat/item/' + copyId + '/circ_list';
             window.open(url, '_blank');
-        }
+        });
     }
 
     showPatron(rows: any[]) {
-        if (rows.length) {
+        const usrIds = Array.from(new Set( rows.map(r => r.usr_id).filter( usr_id => Boolean(usr_id)) ));
+        usrIds.forEach( usrId => {
             const url =
-                '/eg/staff/circ/patron/' + rows[0].usr_id + '/checkout';
+                '/eg/staff/circ/patron/' + usrId + '/checkout';
             window.open(url, '_blank');
-        }
+        });
     }
 
     showOrder(rows: any[]) {
@@ -419,7 +431,7 @@ export class HoldsGridComponent implements OnInit {
     }
 
     showTransferDialog(rows: any[]) {
-        const holdIds = rows.map(r => r.id).filter(id => Boolean(id));
+        const holdIds = rows.filter(r => r.hold_type=='T').map(r => r.id).filter(id => Boolean(id));
         if (holdIds.length > 0) {
             this.transferDialog.holdIds = holdIds;
             this.transferDialog.open({}).subscribe(
index 25ff656..48a3df0 100644 (file)
@@ -41,6 +41,8 @@ export class HoldRetargetDialogComponent
     ngOnInit() {}
 
     open(args: NgbModalOptions): Observable<boolean> {
+        this.numSucceeded = 0;
+        this.numFailed = 0;
         this.holdIds = [].concat(this.holdIds); // array-ify ints
         return super.open(args);
     }
index 163aaad..855c5ea 100644 (file)
@@ -46,6 +46,8 @@ export class HoldTransferDialogComponent
     ngOnInit() {}
 
     open(args: NgbModalOptions): Observable<boolean> {
+        this.numSucceeded = 0;
+        this.numFailed = 0;
         this.holdIds = [].concat(this.holdIds); // array-ify ints
 
         this.transferTarget =
index c72a55e..5762f84 100644 (file)
@@ -2175,7 +2175,8 @@ SELECT  h.id, h.request_time, h.capture_time, h.fulfillment_time, h.checkin_time
         h.cancel_note, h.target, h.current_copy, h.fulfillment_staff, h.fulfillment_lib,
         h.request_lib, h.requestor, h.usr, h.selection_ou, h.selection_depth, h.pickup_lib,
         h.hold_type, h.holdable_formats, h.phone_notify, h.email_notify, h.sms_notify,
-        h.sms_carrier, h.frozen, h.thaw_date, h.shelf_time, h.cut_in_line, h.mint_condition,
+        (SELECT name FROM config.sms_carrier WHERE id = h.sms_carrier) AS "sms_carrier",
+        h.frozen, h.thaw_date, h.shelf_time, h.cut_in_line, h.mint_condition,
         h.shelf_expire_time, h.current_shelf_lib, h.behind_desk, h.hopeless_date,
 
         CASE WHEN h.cancel_time IS NOT NULL THEN 6