From: Kyle Huckins Date: Mon, 25 Nov 2019 18:46:59 +0000 (+0000) Subject: lp1849212 Move Course Reserves to Local Admin X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=f1bbbd7b73fe59d8b45c12a45ebeea9c904deed6;p=evergreen%2Fpines.git lp1849212 Move Course Reserves to Local Admin - Move the Course Reserves admin UI to Local Admin instead of Server Admin Signed-off-by: Kyle Huckins Signed-off-by: Jane Sandberg modified: Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html renamed: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.html -> Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-material.component.html renamed: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.ts -> Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-material.component.ts renamed: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.html -> Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html renamed: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.ts -> Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts renamed: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-reserves.module.ts -> Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts renamed: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course.service.ts -> Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course.service.ts renamed: Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/routing.module.ts -> Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts modified: Open-ILS/src/eg2/src/app/staff/admin/local/routing.module.ts modified: Open-ILS/src/eg2/src/app/staff/admin/server/admin-server-splash.component.html modified: Open-ILS/src/eg2/src/app/staff/admin/server/routing.module.ts Signed-off-by: Michele Morgan Signed-off-by: Galen Charlton --- diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html index dde4a3513e..b18dda9da9 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/admin-local-splash.component.html @@ -23,6 +23,8 @@ url="/eg/staff/admin/local/config/circ_matrix_matchpoint"> + + + + + + + + + + + + + {{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-associate-material.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-material.component.ts new file mode 100644 index 0000000000..cb8eeeb317 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-material.component.ts @@ -0,0 +1,174 @@ +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 {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 {ToastService} from '@eg/share/toast/toast.service'; +import {CourseService} from './course.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; + @Input() tempCallNumber: String; + @Input() tempStatus: Number; + @Input() tempLocation: Number; + @Input() tempCircMod: String; + @Input() isModifyingStatus: Boolean; + @Input() isModifyingCircMod: Boolean; + @Input() isModifyingCallNumber: Boolean; + @Input() isModifyingLocation: Boolean; + currentCourse: IdlObject; + materials: any[]; + gridDataSource: GridDataSource; + + constructor( + private auth: AuthService, + private idl: IdlService, + private net: NetService, + private pcrud: PcrudService, + private org: OrgService, + private evt: EventService, + private modal: NgbModal, + private toast: ToastService, + private courseSvc: CourseService + ) { + 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(material => { + material.isdeleted(true); + this.pcrud.autoApply(material).subscribe( + val => { + this.courseSvc.resetItemFields(material, this.currentCourse.owning_lib()); + 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}, + {flesh: 3, flesh_fields: {acp: ['call_number']}}).subscribe(item => { + let material = this.idl.create('acmcm'); + material.item(item.id()); + material.course(this.currentCourse.id()); + if (relationship) material.relationship(relationship); + if (this.isModifyingStatus && this.tempStatus) { + material.original_status(item.status()); + item.status(this.tempStatus); + } + if (this.isModifyingLocation && this.tempLocation) { + material.original_location(item.location()); + item.location(this.tempLocation); + } + if (this.isModifyingCircMod) { + material.original_circ_modifier(item.circ_modifier()); + item.circ_modifier(this.tempCircMod); + if (!this.tempCircMod) item.circ_modifier(null); + } + if (this.isModifyingCallNumber) { + material.original_callnumber(item.call_number()); + } + this.pcrud.create(material).subscribe( + val => { + console.debug('created: ' + val); + let new_cn = item.call_number().label(); + if (this.tempCallNumber) new_cn = this.tempCallNumber; + this.courseSvc.updateItem(item, this.currentCourse.owning_lib(), new_cn, this.isModifyingCallNumber).then(res => { + this.fetchItem(item.id(), relationship); + 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)); + } + }); + + // Cleaning up inputs + this.barcodeInput = ""; + this.relationshipInput = ""; + this.tempStatus = null; + this.tempCircMod = null; + this.tempCallNumber = null; + this.tempLocation = null; + this.isModifyingCallNumber = false; + this.isModifyingCircMod = false; + this.isModifyingLocation = false; + this.isModifyingStatus = false; + }, 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/local/course-reserves/course-list.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html new file mode 100644 index 0000000000..d31f44040e --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + 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 new file mode 100644 index 0000000000..ab9cd3b36e --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts @@ -0,0 +1,212 @@ +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 {CourseService} from './course.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'; +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' +}) + +export class CourseListComponent implements OnInit { + + @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent; + @ViewChild('grid', { static: true }) grid: GridComponent; + @ViewChild('successString', { static: true }) successString: StringComponent; + @ViewChild('createString', { static: false }) createString: StringComponent; + @ViewChild('createErrString', { static: false }) createErrString: StringComponent; + @ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent; + @ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent; + @ViewChild('archiveFailedString', { static: true }) archiveFailedString: StringComponent; + @ViewChild('archiveSuccessString', { static: true }) archiveSuccessString: 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 courseSvc: CourseService, + private net: NetService, + private org: OrgService, + private pcrud: PcrudService, + private toast: ToastService, + ){} + + ngOnInit() { + this.getSource(); + } + + /** + * Gets the data, specified by the class, that is available. + */ + getSource() { + this.grid_source.getRows = (pager: Pager, sort: any[]) => { + const orderBy: any = {}; + if (sort.length) { + // Sort specified from grid + orderBy[this.idl_class] = sort[0].name + ' ' + sort[0].dir; + } else if (this.sort_field) { + // Default sort field + orderBy[this.idl_class] = this.sort_field; + } + const searchOps = { + offset: pager.offset, + limit: pager.limit, + order_by: orderBy + }; + return this.pcrud.retrieveAll(this.idl_class, searchOps, {fleshSelectors: true}); + }; + } + + showEditDialog(standingPenalty: IdlObject): Promise { + this.editDialog.mode = 'update'; + this.editDialog.recordId = standingPenalty['id'](); + return new Promise((resolve, reject) => { + this.editDialog.open({size: this.dialog_size}).subscribe( + result => { + this.successString.current() + .then(str => this.toast.success(str)); + this.grid.reload(); + resolve(result); + }, + error => { + this.updateFailedString.current() + .then(str => this.toast.danger(str)); + reject(error); + } + ); + }); + } + + createNew() { + this.editDialog.mode = 'create'; + this.editDialog.recordId = null; + this.editDialog.record = null; + this.editDialog.open({size: this.dialog_size}).subscribe( + ok => { + this.createString.current() + .then(str => this.toast.success(str)); + this.grid.reload(); + }, + rejection => { + if (!rejection.dismissed) { + this.createErrString.current() + .then(str => this.toast.danger(str)); + } + } + ); + } + + editSelected(fields: IdlObject[]) { + // Edit each IDL thing one at a time + const editOneThing = (field_object: IdlObject) => { + if (!field_object) { return; } + this.showEditDialog(field_object).then( + () => editOneThing(fields.shift())); + }; + editOneThing(fields.shift()); + } + + archiveSelected(course: IdlObject[]) { + this.courseSvc.disassociateMaterials(course).then(res => { + course.forEach(course => { + console.log(course); + course.is_archived(true); + }); + this.pcrud.update(course).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)); + }, () => { + this.grid.reload(); + } + ); + }); + } + + deleteSelected(idl_object: IdlObject[]) { + this.courseSvc.disassociateMaterials(idl_object).then(res => { + idl_object.forEach(idl_object => { + idl_object.isdeleted(true) + }); + this.pcrud.autoApply(idl_object).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)); + }, + () => 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/local/course-reserves/course-reserves.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts new file mode 100644 index 0000000000..6f6eed594a --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts @@ -0,0 +1,28 @@ +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'; +import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-location-select.module'; +import {CourseService} from './course.service' +@NgModule({ + declarations: [ + CourseListComponent, + CourseAssociateMaterialComponent + ], + imports: [ + AdminCommonModule, + CourseReservesRoutingModule, + ItemLocationSelectModule, + TreeModule + ], + exports: [ + ], + providers: [ + CourseService + ] +}) + +export class CourseReservesModule { +} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course.service.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course.service.ts new file mode 100644 index 0000000000..c8b60cc15d --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course.service.ts @@ -0,0 +1,100 @@ +import {AuthService} from '@eg/core/auth.service'; +import {EventService} from '@eg/core/event.service'; +import {IdlObject, IdlService} from '@eg/core/idl.service'; +import {NetService} from '@eg/core/net.service'; +import {PcrudService} from '@eg/core/pcrud.service'; + +export class CourseService { + + constructor( + private auth: AuthService, + private evt: EventService, + private idl: IdlService, + private net: NetService, + private pcrud: PcrudService + ) {} + + disassociateMaterials(courses) { + return new Promise((resolve, reject) => { + let course_ids = []; + let course_library_hash = {}; + courses.forEach(course => { + course_ids.push(course.id()); + course_library_hash[course.id()] = course.owning_lib(); + }); + this.pcrud.search('acmcm', {course: course_ids}).subscribe(material => { + material.isdeleted(true); + this.resetItemFields(material, course_library_hash[material.course()]); + this.pcrud.autoApply(material).subscribe(res => { + console.log(res); + }, err => { + reject(err); + }, () => { + resolve(material); + }); + }, err => { + reject(err) + }, () => { + resolve(courses); + }); + }); + } + + resetItemFields(material, course_lib) { + this.pcrud.retrieve('acp', material.item(), + {flesh: 3, flesh_fields: {acp: ['call_number']}}).subscribe(copy => { + if (material.original_status()) { + copy.status(material.original_status()); + } + if (copy.circ_modifier() != material.original_circ_modifier()) { + copy.circ_modifier(material.original_circ_modifier()); + } + if (material.original_location()) { + copy.location(material.original_location()); + } + if (material.original_callnumber()) { + this.pcrud.retrieve('acn', material.original_callnumber()).subscribe(cn => { + this.updateItem(copy, course_lib, cn.label(), true); + }); + } else { + this.updateItem(copy, course_lib, copy.call_number().label(), false); + } + }); + } + + updateItem(item: IdlObject, course_lib, call_number, updatingVolume) { + return new Promise((resolve, reject) => { + this.pcrud.update(item).subscribe(item_id => { + if (updatingVolume) { + let cn = item.call_number(); + return this.net.request( + 'open-ils.cat', 'open-ils.cat.call_number.find_or_create', + this.auth.token(), call_number, cn.record(), + course_lib, cn.prefix(), cn.suffix(), + cn.label_class() + ).subscribe(res => { + let event = this.evt.parse(res); + if (event) return; + return this.net.request( + 'open-ils.cat', 'open-ils.cat.transfer_copies_to_volume', + this.auth.token(), res.acn_id, [item.id()] + ).subscribe(transfered_res => { + console.debug("Copy transferred to volume with code " + transfered_res); + }, err => { + reject(err); + }, () => { + resolve(item); + }); + }, err => { + reject(err); + }, () => { + resolve(item); + }); + } else { + return this.pcrud.update(item); + } + }); + }); + } + +} \ No newline at end of file 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 new file mode 100644 index 0000000000..84e74ff881 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from '@angular/core'; +import {RouterModule, Routes} from '@angular/router'; +import {CourseListComponent} from './course-list.component'; + +const routes: Routes = [{ + path: '', + component: CourseListComponent +}]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) + +export class CourseReservesRoutingModule {} \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/routing.module.ts index c29e7e643d..e0e5414537 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/routing.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/routing.module.ts @@ -20,6 +20,9 @@ const routes: Routes = [{ path: 'container/carousel', component: AdminCarouselComponent }, { + path: 'asset/course_list', + loadChildren: '@eg/staff/admin/local/course-reserves/course-reserves.module#CourseReservesModule' +}, { path: 'config/standing_penalty', component: StandingPenaltyComponent }, { diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/admin-server-splash.component.html b/Open-ILS/src/eg2/src/app/staff/admin/server/admin-server-splash.component.html index df5b9ef490..de399d6517 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/admin-server-splash.component.html +++ b/Open-ILS/src/eg2/src/app/staff/admin/server/admin-server-splash.component.html @@ -39,8 +39,6 @@ routerLink="/staff/admin/server/config/circ_modifier">
- - - - - - - - - - - - - {{entry.barcode()}} - - - - - - - {{entry._title}} - - - - - {{r.label}} - - \ 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 deleted file mode 100644 index cb8eeeb317..0000000000 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-associate-material.component.ts +++ /dev/null @@ -1,174 +0,0 @@ -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 {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 {ToastService} from '@eg/share/toast/toast.service'; -import {CourseService} from './course.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; - @Input() tempCallNumber: String; - @Input() tempStatus: Number; - @Input() tempLocation: Number; - @Input() tempCircMod: String; - @Input() isModifyingStatus: Boolean; - @Input() isModifyingCircMod: Boolean; - @Input() isModifyingCallNumber: Boolean; - @Input() isModifyingLocation: Boolean; - currentCourse: IdlObject; - materials: any[]; - gridDataSource: GridDataSource; - - constructor( - private auth: AuthService, - private idl: IdlService, - private net: NetService, - private pcrud: PcrudService, - private org: OrgService, - private evt: EventService, - private modal: NgbModal, - private toast: ToastService, - private courseSvc: CourseService - ) { - 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(material => { - material.isdeleted(true); - this.pcrud.autoApply(material).subscribe( - val => { - this.courseSvc.resetItemFields(material, this.currentCourse.owning_lib()); - 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}, - {flesh: 3, flesh_fields: {acp: ['call_number']}}).subscribe(item => { - let material = this.idl.create('acmcm'); - material.item(item.id()); - material.course(this.currentCourse.id()); - if (relationship) material.relationship(relationship); - if (this.isModifyingStatus && this.tempStatus) { - material.original_status(item.status()); - item.status(this.tempStatus); - } - if (this.isModifyingLocation && this.tempLocation) { - material.original_location(item.location()); - item.location(this.tempLocation); - } - if (this.isModifyingCircMod) { - material.original_circ_modifier(item.circ_modifier()); - item.circ_modifier(this.tempCircMod); - if (!this.tempCircMod) item.circ_modifier(null); - } - if (this.isModifyingCallNumber) { - material.original_callnumber(item.call_number()); - } - this.pcrud.create(material).subscribe( - val => { - console.debug('created: ' + val); - let new_cn = item.call_number().label(); - if (this.tempCallNumber) new_cn = this.tempCallNumber; - this.courseSvc.updateItem(item, this.currentCourse.owning_lib(), new_cn, this.isModifyingCallNumber).then(res => { - this.fetchItem(item.id(), relationship); - 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)); - } - }); - - // Cleaning up inputs - this.barcodeInput = ""; - this.relationshipInput = ""; - this.tempStatus = null; - this.tempCircMod = null; - this.tempCallNumber = null; - this.tempLocation = null; - this.isModifyingCallNumber = false; - this.isModifyingCircMod = false; - this.isModifyingLocation = false; - this.isModifyingStatus = false; - }, 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 deleted file mode 100644 index d31f44040e..0000000000 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - -
- - - - - - - - - - - - -
- - - 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 deleted file mode 100644 index ab9cd3b36e..0000000000 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-list.component.ts +++ /dev/null @@ -1,212 +0,0 @@ -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 {CourseService} from './course.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'; -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' -}) - -export class CourseListComponent implements OnInit { - - @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent; - @ViewChild('grid', { static: true }) grid: GridComponent; - @ViewChild('successString', { static: true }) successString: StringComponent; - @ViewChild('createString', { static: false }) createString: StringComponent; - @ViewChild('createErrString', { static: false }) createErrString: StringComponent; - @ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent; - @ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent; - @ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent; - @ViewChild('archiveFailedString', { static: true }) archiveFailedString: StringComponent; - @ViewChild('archiveSuccessString', { static: true }) archiveSuccessString: 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 courseSvc: CourseService, - private net: NetService, - private org: OrgService, - private pcrud: PcrudService, - private toast: ToastService, - ){} - - ngOnInit() { - this.getSource(); - } - - /** - * Gets the data, specified by the class, that is available. - */ - getSource() { - this.grid_source.getRows = (pager: Pager, sort: any[]) => { - const orderBy: any = {}; - if (sort.length) { - // Sort specified from grid - orderBy[this.idl_class] = sort[0].name + ' ' + sort[0].dir; - } else if (this.sort_field) { - // Default sort field - orderBy[this.idl_class] = this.sort_field; - } - const searchOps = { - offset: pager.offset, - limit: pager.limit, - order_by: orderBy - }; - return this.pcrud.retrieveAll(this.idl_class, searchOps, {fleshSelectors: true}); - }; - } - - showEditDialog(standingPenalty: IdlObject): Promise { - this.editDialog.mode = 'update'; - this.editDialog.recordId = standingPenalty['id'](); - return new Promise((resolve, reject) => { - this.editDialog.open({size: this.dialog_size}).subscribe( - result => { - this.successString.current() - .then(str => this.toast.success(str)); - this.grid.reload(); - resolve(result); - }, - error => { - this.updateFailedString.current() - .then(str => this.toast.danger(str)); - reject(error); - } - ); - }); - } - - createNew() { - this.editDialog.mode = 'create'; - this.editDialog.recordId = null; - this.editDialog.record = null; - this.editDialog.open({size: this.dialog_size}).subscribe( - ok => { - this.createString.current() - .then(str => this.toast.success(str)); - this.grid.reload(); - }, - rejection => { - if (!rejection.dismissed) { - this.createErrString.current() - .then(str => this.toast.danger(str)); - } - } - ); - } - - editSelected(fields: IdlObject[]) { - // Edit each IDL thing one at a time - const editOneThing = (field_object: IdlObject) => { - if (!field_object) { return; } - this.showEditDialog(field_object).then( - () => editOneThing(fields.shift())); - }; - editOneThing(fields.shift()); - } - - archiveSelected(course: IdlObject[]) { - this.courseSvc.disassociateMaterials(course).then(res => { - course.forEach(course => { - console.log(course); - course.is_archived(true); - }); - this.pcrud.update(course).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)); - }, () => { - this.grid.reload(); - } - ); - }); - } - - deleteSelected(idl_object: IdlObject[]) { - this.courseSvc.disassociateMaterials(idl_object).then(res => { - idl_object.forEach(idl_object => { - idl_object.isdeleted(true) - }); - this.pcrud.autoApply(idl_object).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)); - }, - () => 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 deleted file mode 100644 index 6f6eed594a..0000000000 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course-reserves.module.ts +++ /dev/null @@ -1,28 +0,0 @@ -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'; -import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-location-select.module'; -import {CourseService} from './course.service' -@NgModule({ - declarations: [ - CourseListComponent, - CourseAssociateMaterialComponent - ], - imports: [ - AdminCommonModule, - CourseReservesRoutingModule, - ItemLocationSelectModule, - TreeModule - ], - exports: [ - ], - providers: [ - CourseService - ] -}) - -export class CourseReservesModule { -} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course.service.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course.service.ts deleted file mode 100644 index c8b60cc15d..0000000000 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/course.service.ts +++ /dev/null @@ -1,100 +0,0 @@ -import {AuthService} from '@eg/core/auth.service'; -import {EventService} from '@eg/core/event.service'; -import {IdlObject, IdlService} from '@eg/core/idl.service'; -import {NetService} from '@eg/core/net.service'; -import {PcrudService} from '@eg/core/pcrud.service'; - -export class CourseService { - - constructor( - private auth: AuthService, - private evt: EventService, - private idl: IdlService, - private net: NetService, - private pcrud: PcrudService - ) {} - - disassociateMaterials(courses) { - return new Promise((resolve, reject) => { - let course_ids = []; - let course_library_hash = {}; - courses.forEach(course => { - course_ids.push(course.id()); - course_library_hash[course.id()] = course.owning_lib(); - }); - this.pcrud.search('acmcm', {course: course_ids}).subscribe(material => { - material.isdeleted(true); - this.resetItemFields(material, course_library_hash[material.course()]); - this.pcrud.autoApply(material).subscribe(res => { - console.log(res); - }, err => { - reject(err); - }, () => { - resolve(material); - }); - }, err => { - reject(err) - }, () => { - resolve(courses); - }); - }); - } - - resetItemFields(material, course_lib) { - this.pcrud.retrieve('acp', material.item(), - {flesh: 3, flesh_fields: {acp: ['call_number']}}).subscribe(copy => { - if (material.original_status()) { - copy.status(material.original_status()); - } - if (copy.circ_modifier() != material.original_circ_modifier()) { - copy.circ_modifier(material.original_circ_modifier()); - } - if (material.original_location()) { - copy.location(material.original_location()); - } - if (material.original_callnumber()) { - this.pcrud.retrieve('acn', material.original_callnumber()).subscribe(cn => { - this.updateItem(copy, course_lib, cn.label(), true); - }); - } else { - this.updateItem(copy, course_lib, copy.call_number().label(), false); - } - }); - } - - updateItem(item: IdlObject, course_lib, call_number, updatingVolume) { - return new Promise((resolve, reject) => { - this.pcrud.update(item).subscribe(item_id => { - if (updatingVolume) { - let cn = item.call_number(); - return this.net.request( - 'open-ils.cat', 'open-ils.cat.call_number.find_or_create', - this.auth.token(), call_number, cn.record(), - course_lib, cn.prefix(), cn.suffix(), - cn.label_class() - ).subscribe(res => { - let event = this.evt.parse(res); - if (event) return; - return this.net.request( - 'open-ils.cat', 'open-ils.cat.transfer_copies_to_volume', - this.auth.token(), res.acn_id, [item.id()] - ).subscribe(transfered_res => { - console.debug("Copy transferred to volume with code " + transfered_res); - }, err => { - reject(err); - }, () => { - resolve(item); - }); - }, err => { - reject(err); - }, () => { - resolve(item); - }); - } else { - return this.pcrud.update(item); - } - }); - }); - } - -} \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/routing.module.ts deleted file mode 100644 index 84e74ff881..0000000000 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/course-reserves/routing.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {NgModule} from '@angular/core'; -import {RouterModule, Routes} from '@angular/router'; -import {CourseListComponent} from './course-list.component'; - -const routes: Routes = [{ - path: '', - component: CourseListComponent -}]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) - -export class CourseReservesRoutingModule {} \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/routing.module.ts index fe4d35463f..194a979052 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/server/routing.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/server/routing.module.ts @@ -23,9 +23,6 @@ const routes: Routes = [{ path: 'permission/grp_tree', component: PermGroupTreeComponent }, { - path: 'asset/course_list', - loadChildren: '@eg/staff/admin/server/course-reserves/course-reserves.module#CourseReservesModule' -}, { path: 'actor/org_unit', loadChildren: () => import('./org-unit.module').then(m => m.OrgUnitModule)