1 import {Component, Input, ViewChild} from '@angular/core';
2 import {Observable, throwError, from, empty} 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 {ToastService} from '@eg/share/toast/toast.service';
7 import {AuthService} from '@eg/core/auth.service';
8 import {PcrudService} from '@eg/core/pcrud.service';
9 import {OrgService} from '@eg/core/org.service';
10 import {StringComponent} from '@eg/share/string/string.component';
11 import {DialogComponent} from '@eg/share/dialog/dialog.component';
12 import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
15 * Dialog for managing copy notes.
18 export interface CopyNotesChanges {
19 newNotes: IdlObject[];
20 delNotes: IdlObject[];
24 selector: 'eg-copy-notes-dialog',
25 templateUrl: 'copy-notes-dialog.component.html'
28 export class CopyNotesDialogComponent
29 extends DialogComponent {
31 // If there are multiple copyIds, only new notes may be applied.
32 // If there is only one copyId, then notes may be applied or removed.
33 @Input() copyIds: number[] = [];
35 mode: string; // create | manage | edit
37 // If true, no attempt is made to save the new notes to the
38 // database. It's assumed this takes place in the calling code.
39 @Input() inPlaceCreateMode = false;
41 // In 'create' mode, we may be adding notes to multiple copies.
42 copies: IdlObject[] = [];
44 // In 'manage' mode we only handle a single copy.
49 curNotePublic = false;
50 newNotes: IdlObject[] = [];
51 delNotes: IdlObject[] = [];
57 @ViewChild('successMsg', { static: true }) private successMsg: StringComponent;
58 @ViewChild('errorMsg', { static: true }) private errorMsg: StringComponent;
61 private modal: NgbModal, // required for passing to parent
62 private toast: ToastService,
63 private net: NetService,
64 private idl: IdlService,
65 private pcrud: PcrudService,
66 private org: OrgService,
67 private auth: AuthService) {
68 super(modal); // required for subclassing
73 open(args: NgbModalOptions): Observable<CopyNotesChanges> {
79 if (this.copyIds.length === 0 && !this.inPlaceCreateMode) {
80 return throwError('copy ID required');
83 // In manage mode, we can only manage a single copy.
84 // But in create mode, we can add notes to multiple copies.
85 // We can only manage copies that already exist in the database.
86 if (this.copyIds.length === 1 && this.copyIds[0] > 0) {
92 // Observify data loading
93 const obs = from(this.getCopies());
95 // Return open() observable to caller
96 return obs.pipe(switchMap(_ => super.open(args)));
99 getCopies(): Promise<any> {
101 // Avoid fetch if we're only adding notes to isnew copies.
102 const ids = this.copyIds.filter(id => id > 0);
103 if (ids.length === 0) { return Promise.resolve(); }
105 return this.pcrud.search('acp', {id: this.copyIds},
106 {flesh: 1, flesh_fields: {acp: ['notes']}},
109 .toPromise().then(copies => {
110 this.copies = copies;
111 if (copies.length === 1) {
112 this.copy = copies[0];
117 editNote(note: IdlObject) {
118 this.idToEdit = note.id();
123 this.getCopies().then(() => {
124 this.idToEdit = null;
125 this.mode = 'manage';
129 removeNote(note: IdlObject) {
130 this.newNotes = this.newNotes.filter(t => t.id() !== note.id());
132 if (note.isnew() || this.mode === 'create') { return; }
134 const existing = this.copy.notes().filter(n => n.id() === note.id())[0];
135 if (!existing) { return; }
137 existing.isdeleted(true);
138 this.delNotes.push(existing);
140 // Remove from copy for dialog display
141 this.copy.notes(this.copy.notes().filter(n => n.id() !== note.id()));
145 if (!this.curNoteTitle || !this.curNote) { return; }
147 const note = this.idl.create('acpn');
149 note.creator(this.auth.user().id());
150 note.pub(this.curNotePublic ? 't' : 'f');
151 note.title(this.curNoteTitle);
152 note.value(this.curNote);
153 note.id(this.autoId--);
155 this.newNotes.push(note);
158 this.curNoteTitle = '';
159 this.curNotePublic = false;
164 if (this.inPlaceCreateMode) {
165 this.close({ newNotes: this.newNotes, delNotes: this.delNotes });
170 this.newNotes.forEach(note => {
171 this.copies.forEach(copy => {
172 const n = this.idl.clone(note);
173 n.id(null); // remove temp ID, it will be duped
174 n.owning_copy(copy.id());
179 this.pcrud.create(notes).toPromise()
181 if (this.delNotes.length) {
182 return this.pcrud.remove(this.delNotes).toPromise();
185 this.successMsg.current().then(msg => this.toast.success(msg));
186 this.close({ newNotes: this.newNotes, delNotes: this.delNotes });