1 import {Component, Input, ViewChild, OnInit} from '@angular/core';
2 import {Observable, merge, of, EMPTY} from 'rxjs';
3 import {switchMap} from 'rxjs/operators';
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 {PcrudService} from '@eg/core/pcrud.service';
8 import {Pager} from '@eg/share/util/pager';
9 import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
10 import {GridDataSource} from '@eg/share/grid/grid';
11 import {GridComponent} from '@eg/share/grid/grid.component';
12 import {IdlObject} from '@eg/core/idl.service';
13 import {StringComponent} from '@eg/share/string/string.component';
14 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
15 import {ToastService} from '@eg/share/toast/toast.service';
16 import {CourseService} from '@eg/staff/share/course.service';
19 selector: 'eg-course-associate-material-dialog',
20 templateUrl: './course-associate-material.component.html'
23 export class CourseAssociateMaterialComponent extends DialogComponent implements OnInit {
24 @Input() currentCourse: IdlObject;
25 @Input() courseId: any;
26 @Input() courseIsArchived: string;
27 @Input() displayMode: string;
28 materials: any[] = [];
29 @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
30 @ViewChild('materialsGrid', {static: false}) materialsGrid: GridComponent;
31 @ViewChild('materialDeleteFailedString', { static: true })
32 materialDeleteFailedString: StringComponent;
33 @ViewChild('materialDeleteSuccessString', { static: true })
34 materialDeleteSuccessString: StringComponent;
35 @ViewChild('materialAddSuccessString', { static: true })
36 materialAddSuccessString: StringComponent;
37 @ViewChild('materialAddFailedString', { static: true })
38 materialAddFailedString: StringComponent;
39 @ViewChild('materialEditSuccessString', { static: true })
40 materialEditSuccessString: StringComponent;
41 @ViewChild('materialEditFailedString', { static: true })
42 materialEditFailedString: StringComponent;
43 @ViewChild('materialAddDifferentLibraryString', { static: true })
44 materialAddDifferentLibraryString: StringComponent;
45 @ViewChild('confirmOtherLibraryDialog') confirmOtherLibraryDialog: DialogComponent;
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;
60 associateBriefRecord: (newRecord: string) => void;
61 associateElectronicBibRecord: () => void;
64 private auth: AuthService,
65 private course: CourseService,
66 private net: NetService,
67 private pcrud: PcrudService,
68 private toast: ToastService,
69 private modal: NgbModal
72 this.materialsDataSource = new GridDataSource();
74 this.materialsDataSource.getRows = (pager: Pager, sort: any[]) => {
75 return this.net.request(
77 'open-ils.courses.course_materials.retrieve.fleshed',
78 {course: this.courseId}
84 this.associateBriefRecord = (newRecord: string) => {
85 return this.net.request(
87 'open-ils.courses.attach.biblio_record',
91 this.relationshipInput
93 this.materialsGrid.reload();
94 this.materialAddSuccessString.current()
95 .then(str => this.toast.success(str));
99 this.associateElectronicBibRecord = () => {
100 return this.net.request(
102 'open-ils.courses.attach.electronic_resource',
106 this.relationshipInput
108 this.materialsGrid.reload();
109 this.materialAddSuccessString.current()
110 .then(str => this.toast.success(str));
116 isDialog(): boolean {
117 return this.displayMode === 'dialog';
120 editSelectedMaterials(itemFields: IdlObject[]) {
121 // Edit each IDL thing one at a time
122 const editOneThing = (item: IdlObject) => {
123 if (!item) { return; }
125 this.showEditDialog(item).then(
126 () => editOneThing(itemFields.shift()));
129 editOneThing(itemFields.shift());
132 showEditDialog(courseMaterial: IdlObject): Promise<any> {
133 this.editDialog.mode = 'update';
134 this.editDialog.recordId = courseMaterial.id();
135 return new Promise((resolve, reject) => {
136 this.editDialog.open({size: 'lg'}).subscribe(
138 this.materialEditSuccessString.current()
139 .then(str => this.toast.success(str));
140 this.pcrud.retrieve('acmcm', result).subscribe(material => {
141 if (material.course() !== this.courseId) {
142 this.materialsGrid.reload();
144 courseMaterial.relationship = material.relationship();
150 this.materialEditFailedString.current()
151 .then(str => this.toast.danger(str));
158 associateItem(barcode, relationship) {
161 barcode: barcode.trim(),
162 relationship: relationship,
163 isModifyingCallNumber: this.isModifyingCallNumber,
164 isModifyingCircMod: this.isModifyingCircMod,
165 isModifyingLocation: this.isModifyingLocation,
166 isModifyingStatus: this.isModifyingStatus,
167 tempCircMod: this.tempCircMod,
168 tempLocation: this.tempLocation,
169 tempStatus: this.tempStatus,
170 currentCourse: this.currentCourse
172 this.barcodeInput = null;
174 this.pcrud.search('acp', {barcode: args.barcode}, {
175 flesh: 3, flesh_fields: {acp: ['call_number', 'circ_lib']}
176 }).pipe(switchMap(item => this.handleItemAtDifferentLibrary$(item)))
177 .subscribe((originalItem) => {
178 const associatedMaterial = this.course.associateMaterials(originalItem, args);
179 associatedMaterial.material.then(res => {
180 const item = associatedMaterial.item;
181 let new_cn = item.call_number().label();
182 if (this.tempCallNumber) { new_cn = this.tempCallNumber; }
183 this.course.updateItem(item, this.currentCourse.owning_lib(),
184 new_cn, args.isModifyingCallNumber
186 this.materialsGrid.reload();
187 this.materialAddSuccessString.current()
188 .then(str => this.toast.success(str));
191 this.materialAddFailedString.current()
192 .then(str => this.toast.danger(str));
198 deleteSelectedMaterials(items) {
199 let deleteRequest$ = this.course.detachMaterials(items);
200 merge(...deleteRequest$).subscribe(
202 this.materialDeleteSuccessString.current().then(str => this.toast.success(str));
205 this.materialDeleteFailedString.current()
206 .then(str => this.toast.danger(str));
209 this.materialsGrid.reload();
213 handleItemAtDifferentLibrary$(item: IdlObject): Observable<any> {
214 this.itemCircLib = item.circ_lib().shortname();
215 if (item.circ_lib().id() !== this.currentCourse.owning_lib().id()) {
216 return this.confirmOtherLibraryDialog.open()
217 .pipe(switchMap(confirmed => {
218 if (!confirmed) { return EMPTY; }