1 import {Component, OnInit, Input, ViewChild} from '@angular/core';
2 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
3 import {Observable, empty, of, from} from 'rxjs';
4 import {tap, switchMap} from 'rxjs/operators';
5 import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
6 import {IdlObject} from '@eg/core/idl.service';
7 import {OrgService} from '@eg/core/org.service';
8 import {NetService} from '@eg/core/net.service';
9 import {PcrudService} from '@eg/core/pcrud.service';
10 import {AuthService} from '@eg/core/auth.service';
11 import {PatronService} from '@eg/staff/share/patron/patron.service';
12 import {PatronContextService} from './patron.service';
13 import {CheckoutResult, CircService} from '@eg/staff/share/circ/circ.service';
14 import {PromptDialogComponent} from '@eg/share/dialog/prompt.component';
15 import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
16 import {GridComponent} from '@eg/share/grid/grid.component';
17 import {StoreService} from '@eg/core/store.service';
18 import {ServerStoreService} from '@eg/core/server-store.service';
19 import {AudioService} from '@eg/share/util/audio.service';
20 import {CopyAlertsDialogComponent
21 } from '@eg/staff/share/holdings/copy-alerts-dialog.component';
22 import {CircGridComponent, CircGridEntry} from '@eg/staff/share/circ/grid.component';
25 templateUrl: 'items.component.html',
26 selector: 'eg-patron-items'
28 export class ItemsComponent implements OnInit {
30 // Note we can get the patron id from this.context.patron.id(), but
31 // on a new page load, this requires us to wait for the arrival of
32 // the patron object before we can fetch our circs. This is just simpler.
33 @Input() patronId: number;
35 itemsTab = 'checkouts';
37 mainList: number[] = [];
38 altList: number[] = [];
40 displayLost: number = null; // 1 | 2 | 5 | 6;
41 displayLongOverdue: number = null;
42 displayClaimsReturned: number = null;
43 fetchCheckedIn = true;
44 displayAltList = true;
46 @ViewChild('checkoutsGrid') private checkoutsGrid: CircGridComponent;
47 @ViewChild('otherGrid') private otherGrid: CircGridComponent;
48 @ViewChild('nonCatGrid') private nonCatGrid: CircGridComponent;
51 private org: OrgService,
52 private net: NetService,
53 private pcrud: PcrudService,
54 private auth: AuthService,
55 public circ: CircService,
56 private audio: AudioService,
57 private store: StoreService,
58 private serverStore: ServerStoreService,
59 public patronService: PatronService,
60 public context: PatronContextService
67 load(firstLoad?: boolean): Promise<any> {
71 return this.applyDisplaySettings()
72 .then(_ => this.loadTab(this.itemsTab));
74 return this.loadTab(this.itemsTab)
75 .then(_ => this.context.refreshPatron());
79 tabChange(evt: NgbNavChangeEvent) {
80 this.itemsTab = evt.nextId;
81 setTimeout(() => this.loadTab(this.itemsTab));
84 loadTab(name: string): Promise<any> {
87 if (name === 'checkouts') {
88 promise = this.loadMainGrid();
89 } else if (name === 'other') {
90 promise = this.loadAltGrid();
92 promise = this.loadNonCatGrid();
95 return promise.then(_ => this.loading = false);
98 applyDisplaySettings(): Promise<any> {
100 if (this.displayLost !== null) {
101 // Logic already executed
102 return Promise.resolve();
105 return this.serverStore.getItemBatch([
106 'ui.circ.items_out.lost',
107 'ui.circ.items_out.longoverdue',
108 'ui.circ.items_out.claimsreturned'
112 Number(sets['ui.circ.items_out.lost']) || 2;
113 this.displayLongOverdue =
114 Number(sets['ui.circ.items_out.longoverdue']) || 2;
115 this.displayClaimsReturned =
116 Number(sets['ui.circ.items_out.claimsreturned']) || 2;
118 if (this.displayLost & 4 &&
119 this.displayLongOverdue & 4 &&
120 this.displayClaimsReturned & 4) {
122 // all special types are configured to be hidden once
123 // checked in, so there's no need to fetch checked-in circs.
124 this.fetchCheckedIn = false;
126 if (this.displayLost & 1 &&
127 this.displayLongOverdue & 1 &&
128 this.displayClaimsReturned & 1) {
129 // additionally, if all types are configured to display
130 // in the main list while checked out, nothing will
131 // ever appear in the alternate list, so we can hide
132 // the alternate list from the UI.
133 this.displayAltList = false;
139 // Determine which grid ('checkouts' or 'other') a circ should appear in.
140 promoteCircs(list: number[], displayCode: number, xactOpen?: boolean) {
142 if (1 & displayCode) { // bitflag 1 == main list
143 this.mainList = this.mainList.concat(list);
145 this.altList = this.altList.concat(list);
148 if (4 & displayCode) { return; } // bitflag 4 == hide on checkin
149 this.altList = this.altList.concat(list);
153 getCircIds(): Promise<any> {
157 const promise = this.net.request(
159 'open-ils.actor.user.checked_out.authoritative',
160 this.auth.token(), this.patronId
161 ).toPromise().then(checkouts => {
162 this.mainList = checkouts.overdue.concat(checkouts.out);
163 this.promoteCircs(checkouts.lost, this.displayLost, true);
164 this.promoteCircs(checkouts.long_overdue, this.displayLongOverdue, true);
165 this.promoteCircs(checkouts.claims_returned, this.displayClaimsReturned, true);
168 if (!this.fetchCheckedIn) { return promise; }
170 return promise.then(_ => {
171 return this.net.request(
173 'open-ils.actor.user.checked_in_with_fines.authoritative',
174 this.auth.token(), this.patronId
175 ).toPromise().then(checkouts => {
176 this.promoteCircs(checkouts.lost, this.displayLost);
177 this.promoteCircs(checkouts.long_overdue, this.displayLongOverdue);
178 this.promoteCircs(checkouts.claims_returned, this.displayClaimsReturned);
183 loadMainGrid(): Promise<any> {
184 return this.getCircIds()
185 .then(_ => this.checkoutsGrid.load(this.mainList).toPromise())
186 .then(_ => this.checkoutsGrid.reloadGrid());
189 loadAltGrid(): Promise<any> {
190 return this.getCircIds()
191 .then(_ => this.otherGrid.load(this.altList).toPromise())
192 .then(_ => this.otherGrid.reloadGrid());
195 loadNonCatGrid(): Promise<any> {
197 return this.net.request(
199 'open-ils.circ.open_non_cataloged_circulation.user.batch.authoritative',
200 this.auth.token(), this.patronId)
203 const entry: CircGridEntry = {
204 index: `ancc-${circ.id()}`,
205 title: circ.item_type().name(),
206 dueDate: circ.duedate(),
212 this.nonCatGrid.appendGridEntry(entry);
215 .then(_ => this.nonCatGrid.reloadGrid());