From b1327990992179c68e192776d3b757886c19dcdb Mon Sep 17 00:00:00 2001 From: Dan Briem Date: Thu, 9 Mar 2023 20:17:45 +0000 Subject: [PATCH] LP#2009725 Place holds for recent patrons Adds a button to the holds interface to retrieve the last patron or show a dialog of recent patrons depending on the Number of Retrievable Patrons org unit setting. When a patron is loaded in the holds interface, they are added to the recent patrons list. - If the Number of Retrievable Recent Patron setting is < 1, the button doesn't appear. - If the setting is 1 or unset (1 is default), clicking loads the last patron. - If the setting is greater than 1, clicking shows a dialog of recent patrons to select from. - If there are no recent patrons, the button is disabled. Signed-off-by: Dan Briem --- .../src/app/staff/catalog/hold/hold.component.html | 13 ++++- .../src/app/staff/catalog/hold/hold.component.ts | 65 +++++++++++++++++++++- .../share/patron/search-dialog.component.html | 4 +- .../staff/share/patron/search-dialog.component.ts | 5 +- 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.html index d447492cb2..844b2b8284 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.html +++ b/Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.html @@ -1,5 +1,8 @@ + + @@ -33,12 +36,20 @@ -
+
+
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.ts index a74bc37354..22bbd69065 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/catalog/hold/hold.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit, ViewChild} from '@angular/core'; import {Router, ActivatedRoute, ParamMap} from '@angular/router'; -import {tap} from 'rxjs/operators'; +import {filter, map} from 'rxjs/operators'; import {EventService} from '@eg/core/event.service'; import {NetService} from '@eg/core/net.service'; import {AuthService} from '@eg/core/auth.service'; @@ -22,6 +22,7 @@ import {AlertDialogComponent} from '@eg/share/dialog/alert.component'; import {BarcodeSelectComponent } from '@eg/staff/share/barcodes/barcode-select.component'; import {WorkLogService} from '@eg/staff/share/worklog/worklog.service'; +import {StoreService} from '@eg/core/store.service'; class HoldContext { holdMeta: HoldRequestTarget; @@ -97,8 +98,13 @@ export class HoldComponent implements OnInit { // Orgs which are not valid pickup locations disableOrgs: number[] = []; + maxRecentPatrons: number; + recentPatronIds: number[]; + @ViewChild('patronSearch', {static: false}) patronSearch: PatronSearchDialogComponent; + @ViewChild('recentPatronSearch', {static: false}) + recentPatronSearch: PatronSearchDialogComponent; @ViewChild('smsCbox', {static: false}) smsCbox: ComboboxComponent; @ViewChild('barcodeSelect') private barcodeSelect: BarcodeSelectComponent; @@ -120,7 +126,8 @@ export class HoldComponent implements OnInit { private holds: HoldsService, private patron: PatronService, private perm: PermService, - private worklog: WorkLogService + private worklog: WorkLogService, + private localStore: StoreService ) { this.holdContexts = []; this.smsCarriers = []; @@ -160,6 +167,9 @@ export class HoldComponent implements OnInit { } }); + this.store.getItem('ui.staff.max_recent_patrons') + .then(setting => this.maxRecentPatrons = setting ?? 1); + this.net.request('open-ils.actor', 'open-ils.actor.settings.value_for_all_orgs', null, 'opac.holds.org_unit_not_pickup_lib' @@ -425,6 +435,7 @@ export class HoldComponent implements OnInit { this.applyUserSettings(); this.multiHoldsActive = this.canPlaceMultiAt.includes(user.home_ou()); + this.addRecentPatron(user.id()); }); } @@ -722,6 +733,56 @@ export class HoldComponent implements OnInit { ); } + searchRecentPatrons(): void { + const recentPatronIds: number[] = this.recentPatrons(); + + if (this.maxRecentPatrons < 1 || !recentPatronIds.length) { + return; + } + + if (this.maxRecentPatrons > 1 && recentPatronIds.length > 1) { + // open dialog initialized with recent patrons + this.recentPatronIds = recentPatronIds.slice( + 0, this.maxRecentPatrons + ); + this.recentPatronSearch.open({size: 'xl'}).pipe( + filter(patrons => Boolean(patrons?.length)), + map(patrons => patrons[0]) + ).subscribe(user => { + this.userBarcode = user.card().barcode(); + this.userBarcodeChanged(); + }); + } else { + // use the most recent patron's barcode + this.patron.getFleshedById(recentPatronIds[0]) + .then(user => { + if (user) { + this.userBarcode = user.card().barcode(); + this.userBarcodeChanged(); + } + }); + } + } + + recentPatrons(): number[] { + return this.localStore.getLoginSessionItem( + 'eg.circ.recent_patrons' + ) || []; + } + + addRecentPatron(id: number): void { + if (!id || this.maxRecentPatrons < 1) { return; } + + // remove existing matches and make space for the ID + const recentPatrons: number[] = this.recentPatrons() + .filter(recentId => recentId !== id) + .slice(0, this.maxRecentPatrons - 1); + + this.localStore.setLoginSessionItem( + 'eg.circ.recent_patrons', [id, ...recentPatrons] + ); + } + isItemHold(): boolean { return this.holdType === 'C' || this.holdType === 'R' diff --git a/Open-ILS/src/eg2/src/app/staff/share/patron/search-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/patron/search-dialog.component.html index 1006a63c24..383b3bae4c 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/patron/search-dialog.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/patron/search-dialog.component.html @@ -7,7 +7,9 @@