From: Kyle Huckins Date: Fri, 6 Dec 2019 07:17:53 +0000 (+0000) Subject: Course Admin Page X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=e397005e4ecd82d5eaecf3548ff5bd654a0a697b;p=working%2FEvergreen.git Course Admin Page - Double-clicking on a course in the Course Reserves List will up a dedicated admin page for an individual course, featuring tabs for Editing and managing Course Materials. Signed-off-by: Kyle Huckins Changes to be committed: modified: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html modified: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts new file: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.html new file: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.ts modified: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts modified: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts modified: Open-ILS/src/eg2/src/app/staff/share/course.service.ts --- diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html index d31f44040e..2dd917f5b4 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html @@ -3,8 +3,8 @@ - - + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts index 53875f39b0..91c4b2813f 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts @@ -1,4 +1,5 @@ import {Component, Input, ViewChild, OnInit} from '@angular/core'; +import { Router, ActivatedRoute } from '@angular/router'; import {IdlObject} from '@eg/core/idl.service'; import {PcrudService} from '@eg/core/pcrud.service'; import {AuthService} from '@eg/core/auth.service'; @@ -47,11 +48,17 @@ export class CourseListComponent implements OnInit { private net: NetService, private org: OrgService, private pcrud: PcrudService, - private toast: ToastService, + private route: ActivatedRoute, + private router: Router, + private toast: ToastService ){} ngOnInit() { this.getSource(); + this.grid.onRowActivate.subscribe((course:IdlObject) => { + let idToEdit = course.id(); + this.navigateToCoursePage(idToEdit); + }) } /** @@ -76,6 +83,10 @@ export class CourseListComponent implements OnInit { }; } + navigateToCoursePage(id: any) { + this.router.navigate(["/staff/admin/local/asset/course_list/" + id]); + } + showEditDialog(standingPenalty: IdlObject): Promise { this.editDialog.mode = 'update'; this.editDialog.recordId = standingPenalty['id'](); diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.html new file mode 100644 index 0000000000..1d4cf905ad --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.html @@ -0,0 +1,198 @@ + + + + + +
+
+ +
+ + +
+
+
+ + +
+ +
+
+
+
+
+ Barcode +
+ +
+
+
+
+
+
+
+ Relationship +
+ +
+
+
+
+
+ +
+
+
+
+
The following fields will be applied to the material + added, and reverted once the course is no longer associated + with the material.
+
+
+
+
+
+
+
+ Call Number +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+ Circulation Modifier +
+
+ + +
+
+ +
+
+
+
+
+
+
+
+
+
+ Item Status +
+
+ + +
+
+ +
+
+
+
+
+
+
+
+
+
+ Shelving Location +
+
+ + +
+
+ +
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + +
+
+ + + + {{entry.barcode()}} + + + + + + + {{entry._title}} + + + + + {{r.label}} + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.ts new file mode 100644 index 0000000000..f5ed823e8f --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-page.component.ts @@ -0,0 +1,180 @@ +import {Component, Input, ViewChild, OnInit, TemplateRef} from '@angular/core'; +import {Router, ActivatedRoute} from '@angular/router'; +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 {EventService} from '@eg/core/event.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 {StaffBannerComponent} from '@eg/staff/share/staff-banner.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {CourseService} from '@eg/staff/share/course.service'; + +@Component({ + selector: 'eg-course-page', + templateUrl: './course-page.component.html' +}) + +export class CoursePageComponent implements OnInit { + + currentCourse: IdlObject; + courseId: any; + + // Edit Tab + @ViewChild('archiveFailedString', { static: true }) + archiveFailedString: StringComponent; + @ViewChild('archiveSuccessString', { static: true }) + archiveSuccessString: StringComponent; + + // Materials Tab + materials: any[] = []; + @ViewChild('materialsGrid', {static: true}) materialsGrid: GridComponent; + @ViewChild('materialDeleteFailedString', { static: true }) + materialDeleteFailedString: StringComponent; + @ViewChild('materialDeleteSuccessString', { static: true }) + materialDeleteSuccessString: StringComponent; + @ViewChild('materialAddSuccessString', { static: true }) + materialAddSuccessString: StringComponent; + @ViewChild('materialAddFailedString', { static: true }) + materialAddFailedString: StringComponent; + @ViewChild('materialAddDifferentLibraryString', { static: true }) + materialAddDifferentLibraryString: StringComponent; + materialsDataSource: GridDataSource; + @Input() barcodeInput: String; + @Input() relationshipInput: String; + @Input() tempCallNumber: String; + @Input() tempStatus: Number; + @Input() tempLocation: Number; + @Input() tempCircMod: String; + @Input() isModifyingStatus: Boolean; + @Input() isModifyingCircMod: Boolean; + @Input() isModifyingCallNumber: Boolean; + @Input() isModifyingLocation: Boolean; + + constructor( + private auth: AuthService, + private course: CourseService, + private event: EventService, + private idl: IdlService, + private org: OrgService, + private pcrud: PcrudService, + private route: ActivatedRoute, + private toast: ToastService + ) { + this.materialsDataSource = new GridDataSource(); + } + + ngOnInit() { + this.courseId = parseInt(this.route.snapshot.paramMap.get('id')); + this.course.getCourses([this.courseId]).then(course => { + this.currentCourse = course[0]; + }); + this.materialsDataSource.getRows = (pager: Pager, sort: any[]) => { + return this.loadMaterialsGrid(pager); + } + } + + // Edit Tab + archiveCourse() { + this.course.disassociateMaterials(this.currentCourse).then(res => { + this.currentCourse.is_archived(true); + this.pcrud.update(this.currentCourse).subscribe(val => { + console.debug('archived: ' + val); + this.archiveSuccessString.current() + .then(str => this.toast.success(str)); + }, err => { + this.archiveFailedString.current() + .then(str => this.toast.danger(str)); + }); + }); + } + + // Materials Tab + loadMaterialsGrid(pager: Pager): Observable { + return new Observable(observer => { + this.course.getMaterials(this.courseId).then(materials => { + materials.forEach(material => { + this.course.fleshMaterial(material.item(), material.relationship()).then(fleshed_material => { + this.materialsDataSource.data.push(fleshed_material); + }); + }); + }); + observer.complete(); + }); + } + + associateItem(barcode, relationship) { + if (barcode) { + let args = { + barcode: barcode, + relationship: relationship, + isModifyingCallNumber: this.isModifyingCallNumber, + isModifyingCircMod: this.isModifyingCircMod, + isModifyingLocation: this.isModifyingLocation, + isModifyingStatus: this.isModifyingStatus, + tempCircMod: this.tempCircMod, + tempLocation: this.tempLocation, + tempStatus: this.tempStatus, + currentCourse: this.currentCourse + } + this.barcodeInput = null; + + this.pcrud.search('acp', {barcode: args.barcode}, { + flesh: 3, flesh_fields: {acp: ['call_number']} + }).subscribe(item => { + let associatedMaterial = this.course.associateMaterials(item, args); + associatedMaterial.material.then(res => { + item = associatedMaterial.item; + let new_cn = item.call_number().label(); + if (this.tempCallNumber) new_cn = this.tempCallNumber; + this.course.updateItem(item, this.currentCourse.owning_lib(), + new_cn, args.isModifyingCallNumber + ).then(resp => { + this.course.fleshMaterial(item.id(), args.relationship).then(fleshed_material => { + this.materialsDataSource.data.push(fleshed_material); + }); + if (item.circ_lib() != this.currentCourse.owning_lib()) { + this.materialAddDifferentLibraryString.current() + .then(str => this.toast.warning(str)); + } else { + this.materialAddSuccessString.current() + .then(str => this.toast.success(str)); + } + }); + }, err => { + this.materialAddFailedString.current() + .then(str => this.toast.danger(str)); + }); + }); + } + } + + deleteSelected(items) { + let item_ids = []; + items.forEach(item => { + this.materialsDataSource.data.splice(this.materialsDataSource.data.indexOf(item, 0), 1); + item_ids.push(item.id()) + }); + this.pcrud.search('acmcm', {course: this.courseId, item: item_ids}).subscribe(material => { + material.isdeleted(true); + this.pcrud.autoApply(material).subscribe( + val => { + this.course.resetItemFields(material, this.currentCourse.owning_lib()); + console.debug('deleted: ' + val); + this.materialDeleteSuccessString.current().then(str => this.toast.success(str)); + }, + err => { + this.materialDeleteFailedString.current() + .then(str => this.toast.danger(str)); + } + ); + }); + } +} \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts index 0ca63cfab6..180faca887 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts @@ -3,6 +3,7 @@ import {TreeModule} from '@eg/share/tree/tree.module'; import {StaffCommonModule} from '@eg/staff/common.module'; import {AdminCommonModule} from '@eg/staff/admin/common.module'; import {CourseListComponent} from './course-list.component'; +import {CoursePageComponent} from './course-page.component'; import {CourseAssociateMaterialComponent} from './course-associate-material.component'; import {CourseReservesRoutingModule} from './routing.module'; import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-location-select.module'; @@ -10,6 +11,7 @@ import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-loca @NgModule({ declarations: [ CourseListComponent, + CoursePageComponent, CourseAssociateMaterialComponent ], imports: [ diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts index 84e74ff881..7c735dd2dd 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts @@ -1,8 +1,12 @@ import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; import {CourseListComponent} from './course-list.component'; +import {CoursePageComponent} from './course-page.component'; const routes: Routes = [{ + path: ':id', + component: CoursePageComponent +}, { path: '', component: CourseListComponent }]; diff --git a/Open-ILS/src/eg2/src/app/staff/share/course.service.ts b/Open-ILS/src/eg2/src/app/staff/share/course.service.ts index 0856cfd6c1..942130035b 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/course.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/course.service.ts @@ -35,6 +35,37 @@ export class CourseService { } } + getMaterials(course_ids?: Number[]): Promise { + if (!course_ids) { + return this.pcrud.retrieveAll('acmcm', + {}, {atomic: true}).toPromise(); + } else { + return this.pcrud.search('acmcm', {course: course_ids}, + {}, {atomic: true}).toPromise(); + } + } + + fleshMaterial(itemId, relationship?): Promise { + return new Promise((resolve, reject) => { + let item = this.idl.create('acp'); + this.net.request( + 'open-ils.circ', + 'open-ils.circ.copy_details.retrieve', + this.auth.token(), itemId + ).subscribe(res => { + if (res && res.copy) { + item = res.copy; + item.call_number(res.volume); + item._title = res.mvr.title(); + item.circ_lib(this.org.get(item.circ_lib())); + if (relationship) item._relationship = relationship; + } + }, err => { + reject(err); + }, () => resolve(item)); + }); + } + getCoursesFromMaterial(copy_id): Promise { let id_list = []; return new Promise((resolve, reject) => { @@ -45,7 +76,7 @@ export class CourseService { id_list.push(materials.course()); } }, err => { - console.log(err); + console.debug(err); reject(err); }, () => { if (id_list.length) { @@ -81,7 +112,6 @@ export class CourseService { // Creating a new acmcm Entry associateMaterials(item, args) { - console.log("entering associateMaterials") let material = this.idl.create('acmcm'); material.item(item.id()); material.course(args.currentCourse.id()); @@ -124,7 +154,6 @@ export class CourseService { material.isdeleted(true); this.resetItemFields(material, course_library_hash[material.course()]); this.pcrud.autoApply(material).subscribe(res => { - console.log(res); }, err => { reject(err); }, () => { @@ -189,7 +218,11 @@ export class CourseService { resolve(item); }); } else { - return this.pcrud.update(item); + this.pcrud.update(item).subscribe(rse => { + resolve(item); + }, err => { + reject(item); + }); } }); });