LP2016337 Refresh grids in booking return tabs
[evergreen-equinox.git] / Open-ILS / src / eg2 / src / app / staff / booking / return.component.ts
1 import {Component, OnInit, OnDestroy, QueryList, ViewChildren, ViewChild} from '@angular/core';
2 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
3 import {FormGroup, FormControl, Validators} from '@angular/forms';
4 import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
5 import {Observable, from, of, Subscription} from 'rxjs';
6 import { single, switchMap, tap, debounceTime } from 'rxjs/operators';
7 import {PatronService} from '@eg/staff/share/patron/patron.service';
8 import {PcrudService} from '@eg/core/pcrud.service';
9 import {IdlObject} from '@eg/core/idl.service';
10 import {ReservationsGridComponent} from './reservations-grid.component';
11 import {ServerStoreService} from '@eg/core/server-store.service';
12 import {ToastService} from '@eg/share/toast/toast.service';
13 import {PatronBarcodeValidator} from '@eg/share/validators/patron_barcode_validator.directive';
14
15
16 @Component({
17   templateUrl: './return.component.html'
18 })
19
20 export class ReturnComponent implements OnInit, OnDestroy {
21     patronId: number;
22     findPatron: FormGroup;
23     subscriptions: Subscription[] = [];
24     patronTab: any;
25
26     noSelectedRows: (rows: IdlObject[]) => boolean;
27     handleNavChange: ($event: NgbNavChangeEvent) => void;
28     @ViewChild('tabs', { static: true }) tabs: NgbNav;
29     @ViewChildren(ReservationsGridComponent) grids: QueryList<ReservationsGridComponent>;
30
31     constructor(
32         private pcrud: PcrudService,
33         private patron: PatronService,
34         private pbv: PatronBarcodeValidator,
35         private route: ActivatedRoute,
36         private router: Router,
37         private store: ServerStoreService,
38         private toast: ToastService
39     ) {
40     }
41
42
43     ngOnInit() {
44         this.route.paramMap.pipe(switchMap((params: ParamMap) => {
45             return this.handleParams$(params);
46         })).subscribe();
47
48         this.patronTab =
49             this.store.getItem('eg.booking.return.tab')
50             || 'patron_tab';
51
52         this.findPatron = new FormGroup({
53             'patronBarcode': new FormControl(null,
54                 [Validators.required],
55                 [this.pbv.validate]),
56             'resourceBarcode': new FormControl(null,
57                 [Validators.required])
58         });
59
60         const debouncing = 1500;
61         this.subscriptions.push(
62             this.patronBarcode.valueChanges.pipe(
63                 debounceTime(debouncing),
64                 switchMap((val) => {
65                     if ('INVALID' === this.patronBarcode.status) {
66                         this.toast.danger('No patron found with this barcode');
67                         return of();
68                     } else {
69                         return this.patron.bcSearch(val).pipe(
70                             single(),
71                             tap((resp) => { this.router.navigate(['/staff', 'booking', 'return', 'by_patron', resp[0].id]); })
72                         );
73                     }
74                 })
75             )
76             .subscribe());
77
78         this.subscriptions.push(
79             this.resourceBarcode.valueChanges.pipe(
80                 debounceTime(debouncing),
81                 switchMap((val) => {
82                     if ('INVALID' !== this.resourceBarcode.status) {
83                         return this.pcrud.search('brsrc', {'barcode': val}, {
84                             order_by: {'curr_rsrcs': 'pickup_time DESC'},
85                             limit: 1,
86                             flesh: 1,
87                             flesh_fields: {'brsrc': ['curr_rsrcs']},
88                             select: {'curr_rsrcs': {'return_time': null, 'pickup_time': {'!=': null}}}
89                         }).pipe(tap((resp) => {
90                             if (resp.curr_rsrcs()[0].usr()) {
91                                 this.tabs.select('resource');
92                                 this.patronId = resp.curr_rsrcs()[0].usr();
93                                 this.refreshGrids();
94                             }
95                         }));
96                     } else {
97                         return of();
98                     }
99                 })
100             ).subscribe()
101         );
102         this.noSelectedRows = (rows: IdlObject[]) => (rows.length === 0);
103
104         this.handleNavChange = ($event) => {
105             this.store.setItem('eg.booking.return.tab', $event.nextId)
106             .then(() => {
107                 this.router.navigate(['/staff', 'booking', 'return']);
108                 this.findPatron.patchValue({resourceBarcode: ''});
109                 this.patronId = null;
110             });
111         };
112     }
113
114     handleParams$ = (params: ParamMap): Observable<any> => {
115       this.patronId = +params.get('patron_id');
116       if (this.patronId) {
117           return this.pcrud.search('au', {
118               'id': this.patronId,
119           }, {
120               limit: 1,
121               flesh: 1,
122               flesh_fields: {'au': ['card']}
123           }).pipe(tap(
124               (resp) => {
125                   this.tabs.select('patron_tab');
126                   this.findPatron.patchValue({patronBarcode: resp.card().barcode()});
127                   this.refreshGrids();
128               }, (err) => { console.debug(err); }
129           ));
130       } else {
131           return from(this.store.getItem('eg.booking.return.tab'))
132               .pipe(tap(tab => {
133                   if (tab) { this.tabs.select(tab); }
134           }));
135       }
136     }
137     refreshGrids = (): void => {
138         this.grids.forEach (grid => grid.reloadGrid());
139     }
140     get patronBarcode() {
141       return this.findPatron.get('patronBarcode');
142     }
143     get resourceBarcode() {
144       return this.findPatron.get('resourceBarcode');
145     }
146
147     ngOnDestroy(): void {
148       this.subscriptions.forEach((subscription) => {
149           subscription.unsubscribe();
150       });
151     }
152 }