1 import {Component, OnInit, ViewChild} from '@angular/core';
2 import {FormControl, FormGroup, Validators} from '@angular/forms';
3 import {Observable, of, from} from 'rxjs';
4 import {switchMap, mergeMap} from 'rxjs/operators';
5 import {AuthService} from '@eg/core/auth.service';
6 import {GridDataSource} from '@eg/share/grid/grid';
7 import {IdlObject} from '@eg/core/idl.service';
8 import {NetService} from '@eg/core/net.service';
9 import {OrgService} from '@eg/core/org.service';
10 import {PcrudService} from '@eg/core/pcrud.service';
11 import {ReservationActionsService} from './reservation-actions.service';
12 import {CancelReservationDialogComponent} from './cancel-reservation-dialog.component';
13 import {GridComponent} from '@eg/share/grid/grid.component';
14 import {Pager} from '@eg/share/util/pager';
16 // The data that comes from the API, along with some fleshing
17 interface PullListRow {
19 call_number_sortkey?: string;
20 current_resource: IdlObject;
21 reservations: IdlObject[];
22 shelving_location?: string;
23 target_resource_type: IdlObject;
27 templateUrl: './pull-list.component.html'
30 export class PullListComponent implements OnInit {
31 @ViewChild('confirmCancelReservationDialog', { static: true })
32 private cancelReservationDialog: CancelReservationDialogComponent;
34 @ViewChild('pullList', { static: true }) private pullList: GridComponent;
36 public dataSource: GridDataSource = new GridDataSource();
38 public disableOrgs: () => number[];
39 public handleOrgChange: (org: IdlObject) => void;
42 pullListCriteria: FormGroup;
45 private auth: AuthService,
46 private net: NetService,
47 private org: OrgService,
48 private pcrud: PcrudService,
49 private actions: ReservationActionsService,
55 const defaultDaysHence = 5;
56 this.currentOrg = this.auth.user().ws_ou();
58 this.pullListCriteria = new FormGroup({
59 'daysHence': new FormControl(defaultDaysHence, [
64 this.pullListCriteria.valueChanges.subscribe(() => this.pullList.reload() );
66 this.disableOrgs = () => this.org.filterList( { canHaveVolumes : false }, true);
68 this.handleOrgChange = (org: IdlObject) => {
69 this.currentOrg = org.id();
70 this.pullList.reload();
73 this.dataSource.getRows = (pager: Pager) => {
74 const numberOfSecondsInADay = 86400;
75 return this.net.request(
76 'open-ils.booking', 'open-ils.booking.reservations.get_pull_list',
77 this.auth.token(), null,
78 (this.daysHence.value * numberOfSecondsInADay),
80 ).pipe(switchMap(arr => from(arr)), // Change the array we got into a stream
81 mergeMap(resource => this.fleshResource$(resource)) // Add info for cataloged resources
86 noSelectedRows = (rows: IdlObject[]) => (rows.length === 0);
88 notOneResourceSelected = (rows: IdlObject[]) => {
89 return this.actions.notOneUniqueSelected(
90 rows.map(row => { if (row['current_resource']) { return row['current_resource']['id']; }}));
93 notOneCatalogedItemSelected = (rows: IdlObject[]) => {
94 return this.actions.notOneUniqueSelected(
95 rows.filter(row => (row['current_resource'] && row['call_number']))
96 .map(row => row['current_resource'].id())
100 cancelSelected = (rows: IdlObject[]) => {
101 this.cancelReservationDialog.open(rows.map(row => row['reservations'][0].id()));
104 fleshResource$ = (resource: any): Observable<PullListRow> => {
105 if ('t' === resource['target_resource_type'].catalog_item()) {
106 return this.pcrud.search('acp', {
107 'barcode': resource['current_resource'].barcode()
111 flesh_fields: {'acp' : ['call_number', 'location' ]}
112 }).pipe(mergeMap((acp) => {
113 resource['call_number'] = acp.call_number().label();
114 resource['call_number_sortkey'] = acp.call_number().label_sortkey();
115 resource['shelving_location'] = acp.location().name();
123 viewByResource = (reservations: IdlObject[]) => {
124 this.actions.manageReservationsByResource(reservations[0]['current_resource'].barcode());
127 viewItemStatus = (reservations: IdlObject[]) => {
128 this.actions.viewItemStatus(reservations[0]['current_resource'].barcode());
132 return this.pullListCriteria.get('daysHence');