1 import {Component, OnInit, Input, ViewChild} from '@angular/core';
2 import {Observable, throwError, from} from 'rxjs';
3 import {switchMap} from 'rxjs/operators';
4 import {NetService} from '@eg/core/net.service';
5 import {IdlService, IdlObject} from '@eg/core/idl.service';
6 import {EventService} from '@eg/core/event.service';
7 import {ToastService} from '@eg/share/toast/toast.service';
8 import {AuthService} from '@eg/core/auth.service';
9 import {PcrudService} from '@eg/core/pcrud.service';
10 import {OrgService} from '@eg/core/org.service';
11 import {StringComponent} from '@eg/share/string/string.component';
12 import {DialogComponent} from '@eg/share/dialog/dialog.component';
13 import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
14 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
17 * Dialog for managing copy alerts.
21 selector: 'eg-copy-alerts-dialog',
22 templateUrl: 'copy-alerts-dialog.component.html'
25 export class CopyAlertsDialogComponent
26 extends DialogComponent implements OnInit {
28 // If there are multiple copyIds, only new alerts may be applied.
29 // If there is only one copyId, then tags may be applied or removed.
30 @Input() copyIds: number[] = [];
32 mode: string; // create | manage
34 // If true, no attempt is made to save the new alerts to the
35 // database. It's assumed this takes place in the calling code.
36 // This is useful for creating alerts for new copies.
37 @Input() inPlaceMode = false;
39 // In 'create' mode, we may be adding notes to multiple copies.
41 // In 'manage' mode we only handle a single copy.
44 alertTypes: ComboboxEntry[];
48 @ViewChild('successMsg', { static: true }) private successMsg: StringComponent;
49 @ViewChild('errorMsg', { static: true }) private errorMsg: StringComponent;
52 private modal: NgbModal, // required for passing to parent
53 private toast: ToastService,
54 private net: NetService,
55 private idl: IdlService,
56 private pcrud: PcrudService,
57 private org: OrgService,
58 private auth: AuthService) {
59 super(modal); // required for subclassing
67 * Fetch the item/record, then open the dialog.
68 * Dialog promise resolves with true/false indicating whether
69 * the mark-damanged action occured or was dismissed.
71 open(args: NgbModalOptions): Observable<boolean> {
74 this.newAlert = this.idl.create('aca');
75 this.newAlert.create_staff(this.auth.user().id());
77 if (this.copyIds.length === 0 && !this.inPlaceMode) {
78 return throwError('copy ID required');
81 // In manage mode, we can only manage a single copy.
82 // But in create mode, we can add tags to multiple copies.
83 if (this.copyIds.length === 1 && !this.inPlaceMode) {
89 // Observerify data loading
92 .then(_ => this.getCopies())
93 .then(_ => this.mode === 'manage' ? this.getCopyAlerts() : null)
96 // Return open() observable to caller
97 return obs.pipe(switchMap(_ => super.open(args)));
100 getAlertTypes(): Promise<any> {
101 if (this.alertTypes) { return Promise.resolve(); }
103 return this.pcrud.retrieveAll('ccat',
105 scope_org: this.org.ancestors(this.auth.user().ws_ou(), true)
107 ).toPromise().then(alerts => {
108 this.alertTypes = alerts.map(a => ({id: a.id(), label: a.name()}));
112 getCopies(): Promise<any> {
113 if (this.inPlaceMode) { return Promise.resolve(); }
115 return this.pcrud.search('acp', {id: this.copyIds}, {}, {atomic: true})
116 .toPromise().then(copies => {
117 this.copies = copies;
118 copies.forEach(c => c.copy_alerts([]));
119 if (this.mode === 'manage') {
120 this.copy = copies[0];
125 // Copy alerts for the selected copies which have not been
126 // acknowledged by staff and are within org unit range of
128 getCopyAlerts(): Promise<any> {
129 const copyIds = this.copies.map(c => c.id());
130 const typeIds = this.alertTypes.map(a => a.id);
132 return this.pcrud.search('aca',
133 {copy: copyIds, ack_time: null, alert_type: typeIds},
135 .toPromise().then(alerts => {
136 alerts.forEach(a => {
137 const copy = this.copies.filter(c => c.id() === a.copy())[0];
138 copy.copy_alerts().push(a);
143 // Add the in-progress new note to all copies.
145 if (!this.newAlert.alert_type()) { return; }
147 if (this.inPlaceMode) {
148 this.close(this.newAlert);
152 const alerts: IdlObject[] = [];
153 this.copies.forEach(c => {
154 const a = this.idl.clone(this.newAlert);
159 this.pcrud.create(alerts).toPromise().then(
161 this.successMsg.current().then(msg => this.toast.success(msg));
162 this.changesMade = true;
163 if (this.mode === 'create') {
164 // In create mode, we assume the user wants to create
165 // a single alert and be done with it.
166 this.close(this.changesMade);
168 // Otherwise, add the alert to the copy
169 this.copy.copy_alerts().push(newAlert);
173 this.errorMsg.current().then(msg => this.toast.danger(msg));
179 const alerts = this.copy.copy_alerts().filter(a => a.ischanged());
180 if (alerts.length === 0) { return; }
181 this.pcrud.update(alerts).toPromise().then(
182 ok => this.successMsg.current().then(msg => this.toast.success(msg)),
183 err => this.errorMsg.current().then(msg => this.toast.danger(msg))