From bed659a65f15fe64519de1956328d018a1e9e4e9 Mon Sep 17 00:00:00 2001 From: Kyle Huckins Date: Wed, 13 Nov 2019 18:23:08 +0000 Subject: [PATCH] View Course Materials Dialog - Implement dialog to view course materials associated with a particular course in the course list admin UI. - Implement actions to associate and disassociate materials with a specific course. Signed-off-by: Kyle Huckins Changes to be committed: new file: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.html new file: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.ts modified: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.html modified: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.ts modified: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-reserves.module.ts --- .../course-associate-material.component.html | 70 +++++++++++ .../course-associate-material.component.ts | 130 +++++++++++++++++++++ .../course-reserves/course-list.component.html | 4 + .../course-reserves/course-list.component.ts | 55 +++++++++ .../course-reserves/course-reserves.module.ts | 4 +- 5 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.ts diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.html b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.html new file mode 100644 index 0000000000..43fdc822be --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.html @@ -0,0 +1,70 @@ + + + + + + + + + + + + + {{entry.barcode()}} + + + + + + + {{entry._title}} + + + + \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.ts new file mode 100644 index 0000000000..cba573fff2 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.ts @@ -0,0 +1,130 @@ +import {Component, Input, ViewChild, OnInit, TemplateRef} from '@angular/core'; +import {Observable, Observer, of} from 'rxjs'; +import {DialogComponent} from '@eg/share/dialog/dialog.component'; +import {AuthService} from '@eg/core/auth.service'; +import {NetService} from '@eg/core/net.service'; +import {OrgService} from '@eg/core/org.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {Pager} from '@eg/share/util/pager'; +import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap'; +import {GridDataSource} from '@eg/share/grid/grid'; +import {GridComponent} from '@eg/share/grid/grid.component'; +import {IdlObject, IdlService} from '@eg/core/idl.service'; +import {StringComponent} from '@eg/share/string/string.component'; +import {ToastService} from '@eg/share/toast/toast.service'; + +@Component({ + selector: 'eg-course-associate-material-dialog', + templateUrl: './course-associate-material.component.html' +}) + +export class CourseAssociateMaterialComponent extends DialogComponent { + + @ViewChild('materialsGrid', {static: true}) materialsGrid: GridComponent; + @ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent; + @ViewChild('successString', { static: true }) successString: StringComponent; + @ViewChild('failedString', { static: true }) failedString: StringComponent; + @ViewChild('differentLibraryString', { static: true }) differentLibraryString: StringComponent; + @Input() table_name = "Course Materials"; + @Input() barcodeInput: String; + @Input() relationshipInput: String; + currentCourse: IdlObject; + materials: any[]; + gridDataSource: GridDataSource; + + constructor( + private auth: AuthService, + private idl: IdlService, + private net: NetService, + private pcrud: PcrudService, + private org: OrgService, + private modal: NgbModal, + private toast: ToastService + ) { + super(modal); + this.gridDataSource = new GridDataSource(); + } + + ngOnInit() { + this.gridDataSource.getRows = (pager: Pager, sort: any[]) => { + return this.fetchMaterials(pager); + } + } + + deleteSelected(items) { + let item_ids = []; + items.forEach(item => { + this.gridDataSource.data.splice(this.gridDataSource.data.indexOf(item, 0), 1); + item_ids.push(item.id()) + }); + this.pcrud.search('acmcm', {course: this.currentCourse.id(), item: item_ids}).subscribe(res => { + res.isdeleted(true); + this.pcrud.autoApply(res).subscribe( + val => { + console.debug('deleted: ' + val); + this.deleteSuccessString.current().then(str => this.toast.success(str)); + }, + err => { + this.deleteFailedString.current() + .then(str => this.toast.danger(str)); + } + ); + }); + } + + associateItem(barcode, relationship) { + if (barcode) { + this.pcrud.search('acp', {barcode: barcode}).subscribe(item => { + let material = this.idl.create('acmcm'); + material.item(item.id()); + material.course(this.currentCourse.id()); + if (relationship) material.relationship(relationship); + this.pcrud.create(material).subscribe( + val => { + console.debug('created: ' + val); + if (item.circ_lib() != this.currentCourse.owning_lib()) { + this.differentLibraryString.current().then(str => this.toast.warning(str)); + } else { + this.successString.current().then(str => this.toast.success(str)); + } + this.fetchItem(item.id(), relationship); + this.barcodeInput = ""; + this.relationshipInput = ""; + }, err => { + this.failedString.current().then(str => this.toast.danger(str)); + }); + }); + } + } + + fetchMaterials(pager: Pager): Observable { + return new Observable(observer => { + this.materials.forEach(material => { + this.fetchItem(material.item, material.relationship); + }); + observer.complete(); + }); + } + + fetchItem(itemId, relationship): Promise { + return new Promise((resolve, reject) => { + this.net.request( + 'open-ils.circ', + 'open-ils.circ.copy_details.retrieve', + this.auth.token(), itemId + ).subscribe(res => { + if (res) { + let item = res.copy; + item.call_number(res.volume); + item.circ_lib(this.org.get(item.circ_lib())); + item._title = res.mvr.title(); + item._relationship = relationship; + this.gridDataSource.data.push(item); + } + }, err => { + reject(err); + }, () => resolve(this.gridDataSource.data)); + }); + } +} \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.html b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.html index 345197c9c0..eb01af8112 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.html +++ b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.html @@ -7,6 +7,8 @@ + +
+ + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.ts index 05fe7c9889..e806539c49 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.ts @@ -1,6 +1,9 @@ import {Component, Input, ViewChild, OnInit} from '@angular/core'; import {IdlObject} from '@eg/core/idl.service'; import {PcrudService} from '@eg/core/pcrud.service'; +import {AuthService} from '@eg/core/auth.service'; +import {NetService} from '@eg/core/net.service'; +import {OrgService} from '@eg/core/org.service'; import {GridComponent} from '@eg/share/grid/grid.component'; import {Pager} from '@eg/share/util/pager'; import {GridDataSource, GridColumn} from '@eg/share/grid/grid'; @@ -8,6 +11,9 @@ import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component'; import {StringComponent} from '@eg/share/string/string.component'; import {ToastService} from '@eg/share/toast/toast.service'; +import {CourseAssociateMaterialComponent + } from './course-associate-material.component'; + @Component({ templateUrl: './course-list.component.html' }) @@ -22,14 +28,20 @@ export class CourseListComponent implements OnInit { @ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent; @ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent; @ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent; + @ViewChild('courseMaterialDialog', {static: true}) + private courseMaterialDialog: CourseAssociateMaterialComponent; @Input() sort_field: string; @Input() idl_class = "acmc"; @Input() dialog_size: 'sm' | 'lg' = 'lg'; @Input() table_name = "Course"; grid_source: GridDataSource = new GridDataSource(); + currentMaterials: any[] = []; search_value = ''; constructor( + private auth: AuthService, + private net: NetService, + private org: OrgService, private pcrud: PcrudService, private toast: ToastService, ){} @@ -124,5 +136,48 @@ export class CourseListComponent implements OnInit { () => this.grid.reload() ); }; + + fetchCourseMaterials(course, currentMaterials): Promise { + return new Promise((resolve, reject) => { + this.pcrud.search('acmcm', {course: course}).subscribe(res => { + if (res) this.fleshItemDetails(res.item(), res.relationship()); + }, err => { + reject(err); + }, () => resolve(this.courseMaterialDialog.gridDataSource.data)); + }); + } + + fleshItemDetails(itemId, relationship): Promise { + return new Promise((resolve, reject) => { + this.net.request( + 'open-ils.circ', + 'open-ils.circ.copy_details.retrieve', + this.auth.token(), itemId + ).subscribe(res => { + if (res) { + let item = res.copy; + item.call_number(res.volume); + item._title = res.mvr.title(); + item.circ_lib(this.org.get(item.circ_lib())); + item._relationship = relationship; + this.courseMaterialDialog.gridDataSource.data.push(item); + } + }, err => { + reject(err); + }, () => resolve(this.courseMaterialDialog.gridDataSource.data)); + }); + } + + openMaterialsDialog(course) { + let currentMaterials = [] + this.courseMaterialDialog.gridDataSource.data = []; + this.fetchCourseMaterials(course[0].id(), currentMaterials).then(res => { + this.courseMaterialDialog.currentCourse = course[0]; + this.courseMaterialDialog.materials = currentMaterials; + this.courseMaterialDialog.open({size: 'lg'}).subscribe(res => { + console.log(res); + }); + }); + } } diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-reserves.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-reserves.module.ts index 1702ba861e..0518730187 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-reserves.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-reserves.module.ts @@ -2,11 +2,13 @@ import {NgModule} from '@angular/core'; import {TreeModule} from '@eg/share/tree/tree.module'; import {AdminCommonModule} from '@eg/staff/admin/common.module'; import {CourseListComponent} from './course-list.component'; +import {CourseAssociateMaterialComponent} from './course-associate-material.component'; import {CourseReservesRoutingModule} from './routing.module'; @NgModule({ declarations: [ - CourseListComponent + CourseListComponent, + CourseAssociateMaterialComponent ], imports: [ AdminCommonModule, -- 2.11.0