]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/acq/provider/acq-provider.component.ts
7eb6899aa0e488b3853ce9ae50d7ce025beacbed
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / acq / provider / acq-provider.component.ts
1 import {Component, OnInit, AfterViewInit, ViewChild, ChangeDetectorRef, OnDestroy} from '@angular/core';
2 import {filter, takeUntil} from 'rxjs/operators';
3 import {Subject, Observable, of} from 'rxjs';
4 import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
5 import {Router, ActivatedRoute, ParamMap, RouterEvent, NavigationEnd} from '@angular/router';
6 import {StaffCommonModule} from '@eg/staff/common.module';
7 import {IdlService, IdlObject} from '@eg/core/idl.service';
8 import {PcrudService} from '@eg/core/pcrud.service';
9 import {AcqProviderSummaryPaneComponent} from './summary-pane.component';
10 import {ProviderDetailsComponent} from './provider-details.component';
11 import {ProviderHoldingsComponent} from './provider-holdings.component';
12 import {ProviderResultsComponent} from './provider-results.component';
13 import {ProviderRecordService} from './provider-record.service';
14 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
15 import {StringComponent} from '@eg/share/string/string.component';
16 import {ToastService} from '@eg/share/toast/toast.service';
17 import {AuthService} from '@eg/core/auth.service';
18 import {StoreService} from '@eg/core/store.service';
19 import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
20
21 @Component({
22   templateUrl: './acq-provider.component.html'
23 })
24
25 export class AcqProviderComponent implements OnInit, AfterViewInit, OnDestroy {
26
27     activeTab = '';
28     showSearchForm = false;
29     id = null;
30     validTabTypes = ['details', 'addresses', 'contacts', 'attributes', 'holdings', 'edi_accounts', 'purchase_orders', 'invoices'];
31     defaultTabType = 'details';
32     @ViewChild('acqSearchProviderSummary', { static: true }) providerSummaryPane: AcqProviderSummaryPaneComponent;
33     @ViewChild('acqProviderResults', { static: true }) acqProviderResults: ProviderResultsComponent;
34     @ViewChild('providerDetails', { static: false }) providerDetails: ProviderDetailsComponent;
35     @ViewChild('providerHoldings', { static: false }) providerHoldings: ProviderHoldingsComponent;
36     @ViewChild('createDialog', { static: true }) createDialog: FmRecordEditorComponent;
37     @ViewChild('createString', { static: false }) createString: StringComponent;
38     @ViewChild('createErrString', { static: false }) createErrString: StringComponent;
39     @ViewChild('leaveConfirm', { static: true }) leaveConfirm: ConfirmDialogComponent;
40
41     onTabChange: ($event: NgbTabChangeEvent) => void;
42
43     onDesireSummarize: ($event: number, updateSummaryOnly?: boolean, hideSearchForm?: boolean) => void;
44     onSummaryToggled: ($event: boolean) => void;
45
46     previousUrl: string = null;
47     public destroyed = new Subject<any>();
48     _alreadyDeactivated = false;
49
50     constructor(
51         private router: Router,
52         private route: ActivatedRoute,
53         private auth: AuthService,
54         private pcrud: PcrudService,
55         private idl: IdlService,
56         private providerRecord: ProviderRecordService,
57         private toast: ToastService,
58         private store: StoreService,
59         private changeDetector: ChangeDetectorRef
60     ) {
61         this.router.events.pipe(
62             filter((event: RouterEvent) => event instanceof NavigationEnd),
63             takeUntil(this.destroyed)
64         ).subscribe(routeEvent => {
65             if (routeEvent instanceof NavigationEnd) {
66                 if (this.previousUrl != null &&
67                     routeEvent.url === '/staff/acq/provider') {
68                     this.acqProviderResults.resetSearch();
69                     this.showSearchForm = true;
70                     this.id = null;
71                 }
72                 this.previousUrl = routeEvent.url;
73             }
74         });
75     }
76
77     ngOnInit() {
78         const self = this;
79
80         const tabTypeParam = this.route.snapshot.paramMap.get('tab');
81         const idParam = this.route.snapshot.paramMap.get('id');
82
83         this.defaultTabType =
84             this.store.getLocalItem('eg.acq.provider.default_tab') || 'details';
85
86         const keepSearchForm = history.state.hasOwnProperty('keepSearchForm') ?
87                                   history.state.keepSearchForm :
88                                   false;
89         if (keepSearchForm) {
90             this.showSearchForm = true;
91         }
92
93         if (idParam) {
94             if (!keepSearchForm) {
95                 this.showSearchForm = false;
96             }
97             this.id = idParam;
98             if (!tabTypeParam) {
99                 this.activeTab = this.defaultTabType;
100                 this.router.navigate(['/staff', 'acq', 'provider', this.id, this.activeTab]);
101             }
102         }
103
104         if (tabTypeParam) {
105             if (!keepSearchForm) {
106                 this.showSearchForm = false;
107             }
108             if (this.validTabTypes.includes(tabTypeParam)) {
109                 this.activeTab = tabTypeParam;
110             } else {
111                 this.activeTab = this.defaultTabType;
112                 this.router.navigate(['/staff', 'acq', 'provider', this.id, this.activeTab]);
113             }
114         } else {
115             this.showSearchForm = true;
116         }
117
118         this.onTabChange = ($event) => {
119             $event.preventDefault();
120             this.canDeactivate().subscribe(canLeave => {
121                 if (!canLeave) { return; }
122                 this._alreadyDeactivated = true; // don't trigger again on the route change
123                 if (this.validTabTypes.includes($event.nextId)) {
124                     this.activeTab = $event.nextId;
125                     const id = this.route.snapshot.paramMap.get('id');
126                     this.router.navigate(['/staff', 'acq', 'provider', this.id, $event.nextId]);
127                 }
128             });
129         };
130
131         this.onDesireSummarize = ($event, updateSummaryOnly = false, hideSearchForm = true) => {
132             this.id = $event;
133             this.providerRecord.fetch(this.id).then(() => {
134                 // $event is a provider ID
135                 this.providerSummaryPane.update($event);
136                 if (this.providerDetails) {
137                     this.providerDetails.refresh();
138                 }
139                 if (updateSummaryOnly) {
140                     return;
141                 }
142                 this.providerRecord.announceProviderUpdated();
143                 if (hideSearchForm) {
144                     this.showSearchForm = false;
145                 }
146                 this.activeTab = this.defaultTabType;
147                 this.router.navigate(
148                     ['/staff', 'acq', 'provider', this.id, this.activeTab],
149                     { state: { keepSearchForm: !hideSearchForm } }
150                 );
151             });
152         };
153
154         this.onSummaryToggled = ($event) => {
155             // in case this is useful for a better implementation of reflowing the UI
156         };
157     }
158
159     ngAfterViewInit() {
160         this.changeDetector.detectChanges();
161     }
162
163     ngOnDestroy(): void {
164         this.destroyed.next();
165         this.destroyed.complete();
166     }
167
168     setDefaultTab() {
169         this.defaultTabType = this.activeTab;
170         this.store.setLocalItem('eg.acq.provider.default_tab', this.activeTab);
171     }
172
173     createNew() {
174         this.createDialog.mode = 'create';
175         const provider = this.idl.create('acqpro');
176         provider.active(true);
177         provider.owner(this.auth.user().ws_ou());
178         provider.default_copy_count(1);
179         this.createDialog.record = provider;
180         this.createDialog.recordId = null;
181         this.createDialog.open({size: 'lg'}).subscribe(
182             ok => {
183                 this.createString.current()
184                     .then(str => this.toast.success(str));
185                 this.onDesireSummarize(ok.id());
186             },
187             rejection => {
188                 if (!rejection.dismissed) {
189                     this.createErrString.current()
190                         .then(str => this.toast.danger(str));
191                 }
192             }
193         );
194     }
195
196     canDeactivate(): Observable<boolean> {
197         if (this._alreadyDeactivated) {
198             // one freebie
199             this._alreadyDeactivated = false;
200             return of(true);
201         }
202         if ((this.providerHoldings && this.providerHoldings.isDirty()) ||
203             (this.providerDetails && this.providerDetails.isDirty())) {
204             return this.leaveConfirm.open();
205         } else {
206             return of(true);
207         }
208     }
209 }