<eg-patron-search-dialog #patronSearch></eg-patron-search-dialog>
+<eg-patron-search-dialog #recentPatronSearch
+ [patronIds]="recentPatronIds">
+</eg-patron-search-dialog>
<eg-barcode-select #barcodeSelect></eg-barcode-select>
<eg-worklog-strings-components></eg-worklog-strings-components>
</h3>
</ng-container>
</div>
- <div class="col-lg-2">
+ <div class="col-lg-6">
<button class="btn btn-outline-dark btn-sm" (click)="searchPatrons()">
<span class="material-icons mat-icon-in-button align-middle"
i18n-title title="Search for Patron">search</span>
<span class="align-middle" i18n>Search for Patron</span>
</button>
+ <button class="btn btn-outline-dark btn-sm ml-2"
+ *ngIf="maxRecentPatrons > 0"
+ [disabled]="!recentPatrons().length"
+ (click)="searchRecentPatrons()">
+ <span class="material-icons mat-icon-in-button align-middle"
+ i18n-title title="Recent Patron(s)">person</span>
+ <span class="align-middle" i18n>Recent Patron(s)</span>
+ </button>
</div>
</div>
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';
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;
// 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;
private holds: HoldsService,
private patron: PatronService,
private perm: PermService,
- private worklog: WorkLogService
+ private worklog: WorkLogService,
+ private localStore: StoreService
) {
this.holdContexts = [];
this.smsCarriers = [];
}
});
+ 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'
this.applyUserSettings();
this.multiHoldsActive =
this.canPlaceMultiAt.includes(user.home_ou());
+ this.addRecentPatron(user.id());
});
}
);
}
+ 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'