]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-material.component.ts
LP1849212: Allow users to detach all types of materials from courses
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / admin / local / course-reserves / course-associate-material.component.ts
1 import {Component, Input, ViewChild, OnInit, TemplateRef} from '@angular/core';
2 import {ActivatedRoute} from '@angular/router';
3 import {from, merge, Observable} from 'rxjs';
4 import {DialogComponent} from '@eg/share/dialog/dialog.component';
5 import {AuthService} from '@eg/core/auth.service';
6 import {NetService} from '@eg/core/net.service';
7 import {EventService} from '@eg/core/event.service';
8 import {OrgService} from '@eg/core/org.service';
9 import {PcrudService} from '@eg/core/pcrud.service';
10 import {Pager} from '@eg/share/util/pager';
11 import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
12 import {GridDataSource} from '@eg/share/grid/grid';
13 import {GridComponent} from '@eg/share/grid/grid.component';
14 import {IdlObject, IdlService} from '@eg/core/idl.service';
15 import {StringComponent} from '@eg/share/string/string.component';
16 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
17 import {ToastService} from '@eg/share/toast/toast.service';
18 import {CourseService} from '@eg/staff/share/course.service';
19
20 @Component({
21     selector: 'eg-course-associate-material-dialog',
22     templateUrl: './course-associate-material.component.html'
23 })
24
25 export class CourseAssociateMaterialComponent extends DialogComponent implements OnInit {
26     @Input() currentCourse: IdlObject;
27     @Input() courseId: any;
28     @Input() displayMode: String;
29     materials: any[] = [];
30     @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
31     @ViewChild('materialsGrid', {static: false}) materialsGrid: GridComponent;
32     @ViewChild('materialDeleteFailedString', { static: true })
33         materialDeleteFailedString: StringComponent;
34     @ViewChild('materialDeleteSuccessString', { static: true })
35         materialDeleteSuccessString: StringComponent;
36     @ViewChild('materialAddSuccessString', { static: true })
37         materialAddSuccessString: StringComponent;
38     @ViewChild('materialAddFailedString', { static: true })
39         materialAddFailedString: StringComponent;
40     @ViewChild('materialEditSuccessString', { static: true })
41         materialEditSuccessString: StringComponent;
42     @ViewChild('materialEditFailedString', { static: true })
43         materialEditFailedString: StringComponent;
44     @ViewChild('materialAddDifferentLibraryString', { static: true })
45         materialAddDifferentLibraryString: StringComponent;
46     materialsDataSource: GridDataSource;
47     @Input() barcodeInput: String;
48     @Input() relationshipInput: String;
49     @Input() tempCallNumber: String;
50     @Input() tempStatus: Number;
51     @Input() tempLocation: Number;
52     @Input() tempCircMod: String;
53     @Input() isModifyingStatus: Boolean;
54     @Input() isModifyingCircMod: Boolean;
55     @Input() isModifyingCallNumber: Boolean;
56     @Input() isModifyingLocation: Boolean;
57     bibId: number;
58
59     associateBriefRecord: (newRecord: string) => void;
60     associateElectronicBibRecord: () => void;
61
62     constructor(
63         private auth: AuthService,
64         private course: CourseService,
65         private event: EventService,
66         private idl: IdlService,
67         private net: NetService,
68         private org: OrgService,
69         private pcrud: PcrudService,
70         private route: ActivatedRoute,
71         private toast: ToastService,
72         private modal: NgbModal
73     ) {
74         super(modal);
75         this.materialsDataSource = new GridDataSource();
76
77         this.materialsDataSource.getRows = (pager: Pager, sort: any[]) => {
78             return this.net.request(
79                 'open-ils.courses',
80                 'open-ils.courses.course_materials.retrieve.fleshed',
81                 {course: this.courseId}
82             );
83         };
84     }
85
86     ngOnInit() {
87         this.associateBriefRecord = (newRecord: string) => {
88             return this.net.request(
89                 'open-ils.courses',
90                 'open-ils.courses.attach.biblio_record',
91                 this.auth.token(),
92                 newRecord,
93                 this.courseId,
94                 this.relationshipInput
95             ).subscribe(() => {
96                 this.materialsGrid.reload();
97                 this.materialAddSuccessString.current()
98                     .then(str => this.toast.success(str));
99             });
100         };
101
102         this.associateElectronicBibRecord = () => {
103             return this.net.request(
104                 'open-ils.courses',
105                 'open-ils.courses.attach.electronic_resource',
106                 this.auth.token(),
107                 this.bibId,
108                 this.courseId,
109                 this.relationshipInput
110             ).subscribe(() => {
111                 this.materialsGrid.reload();
112                 this.materialAddSuccessString.current()
113                     .then(str => this.toast.success(str));
114             });
115          };
116
117     }
118
119     isDialog(): boolean {
120         return this.displayMode === 'dialog';
121     }
122
123     editSelectedMaterials(itemFields: IdlObject[]) {
124         // Edit each IDL thing one at a time
125         const editOneThing = (item: IdlObject) => {
126             if (!item) { return; }
127
128             this.showEditDialog(item).then(
129                 () => editOneThing(itemFields.shift()));
130         };
131
132         editOneThing(itemFields.shift());
133     }
134
135     showEditDialog(course_material: IdlObject): Promise<any> {
136         this.editDialog.mode = 'update';
137         this.editDialog.recordId = course_material._id;
138         return new Promise((resolve, reject) => {
139             this.editDialog.open({size: 'lg'}).subscribe(
140                 result => {
141                     this.materialEditSuccessString.current()
142                         .then(str => this.toast.success(str));
143                     this.pcrud.retrieve('acmcm', result).subscribe(material => {
144                         if (material.course() !== this.courseId) {
145                             this.materialsDataSource.data.splice(
146                                 this.materialsDataSource.data.indexOf(course_material, 0), 1
147                             );
148                         } else {
149                             course_material._relationship = material.relationship();
150                         }
151                     });
152                     resolve(result);
153                 },
154                 error => {
155                     this.materialEditFailedString.current()
156                         .then(str => this.toast.danger(str));
157                     reject(error);
158                 }
159             );
160         });
161     }
162
163     associateItem(barcode, relationship) {
164         if (barcode) {
165             const args = {
166                 barcode: barcode,
167                 relationship: relationship,
168                 isModifyingCallNumber: this.isModifyingCallNumber,
169                 isModifyingCircMod: this.isModifyingCircMod,
170                 isModifyingLocation: this.isModifyingLocation,
171                 isModifyingStatus: this.isModifyingStatus,
172                 tempCircMod: this.tempCircMod,
173                 tempLocation: this.tempLocation,
174                 tempStatus: this.tempStatus,
175                 currentCourse: this.currentCourse
176             };
177             this.barcodeInput = null;
178
179             this.pcrud.search('acp', {barcode: args.barcode}, {
180                 flesh: 3, flesh_fields: {acp: ['call_number']}
181             }).subscribe(item => {
182                 const associatedMaterial = this.course.associateMaterials(item, args);
183                 associatedMaterial.material.then(res => {
184                     item = associatedMaterial.item;
185                     let new_cn = item.call_number().label();
186                     if (this.tempCallNumber) { new_cn = this.tempCallNumber; }
187                     this.course.updateItem(item, this.currentCourse.owning_lib(),
188                         new_cn, args.isModifyingCallNumber
189                     ).then(resp => {
190                         this.materialsGrid.reload();
191                         if (item.circ_lib() !== this.currentCourse.owning_lib()) {
192                             this.materialAddDifferentLibraryString.current()
193                             .then(str => this.toast.warning(str));
194                         } else {
195                             this.materialAddSuccessString.current()
196                             .then(str => this.toast.success(str));
197                         }
198                     });
199                 }, err => {
200                     this.materialAddFailedString.current()
201                     .then(str => this.toast.danger(str));
202                 });
203             });
204         }
205     }
206
207     deleteSelectedMaterials(items) {
208         const deleteRequest$ = [];
209         items.forEach(item => {
210             deleteRequest$.push(this.net.request(
211                 'open-ils.courses', 'open-ils.courses.detach_material',
212                 this.auth.token(), item.id()));
213         });
214         merge(...deleteRequest$).subscribe(
215             val => {
216                 this.materialDeleteSuccessString.current().then(str => this.toast.success(str));
217             },
218             err => {
219                 this.materialDeleteFailedString.current()
220                     .then(str => this.toast.danger(str));
221             }
222         );
223     }
224 }