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