From ae9dcf4670f8b3e0e4b06d5157b533faeb546adf Mon Sep 17 00:00:00 2001 From: Zavier Banks Date: Mon, 9 Dec 2019 16:52:39 +0000 Subject: [PATCH] LP1849212 Associtate and Disassociate Course With Instructors Creating a component that associates and disassociates instructors with courses using the course list. Signed-off-by: Zavier Banks Signed-off-by: Michele Morgan Signed-off-by: Galen Charlton --- Open-ILS/examples/fm_IDL.xml | 2 +- .../course-associate-users.component.html | 57 ++++++++++ .../course-associate-users.component.ts | 102 ++++++++++++++++++ .../course-list.component.html | 6 ++ .../course-reserves/course-list.component.ts | 59 +++++++++- .../course-reserves/course-reserves.module.ts | 4 +- .../eg2/src/app/staff/share/course.service.ts | 25 +++++ 7 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-users.component.html create mode 100644 Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-users.component.ts diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index b96a83d97e..db6946f293 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -3165,7 +3165,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-users.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-users.component.html new file mode 100644 index 0000000000..079acd7167 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-users.component.html @@ -0,0 +1,57 @@ + + + + + + + + + \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-users.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-users.component.ts new file mode 100644 index 0000000000..b3be2c45f8 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-associate-users.component.ts @@ -0,0 +1,102 @@ +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 '@eg/staff/share/course.service'; + +@Component({ + selector: 'eg-course-associate-users-dialog', + templateUrl: './course-associate-users.component.html' +}) + +export class CourseAssociateUsersComponent extends DialogComponent { + + @ViewChild('usersGrid', {static: true}) usersGrid: 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 Users"; + @Input() userRoleInput: String; + + idl_class = "acmcu"; + new_usr:any; + currentCourse: IdlObject; + users: 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() { + } + + /** + * Takes the user id and creates a course user based around it. + * @param user_input The inputted user Id. + */ + associateUsers(user_input) { + if (user_input) { + let user = this.idl.create('acmcu'); + user.course(this.currentCourse.id()); + user.usr(this.new_usr); + user.usr_role(user_input); + this.pcrud.create(user).subscribe( + val => { + console.debug('created: ' + val); + this.successString.current().then(str => this.toast.success(str)); + }, err => { + this.failedString.current().then(str => this.toast.danger(str)); + }) + } + } + + /** + * Delete a user based on the id selected from the grid. + * @param users + */ + deleteSelected(users) { + let user_ids = []; + users.forEach(user => { + this.gridDataSource.data.splice(this.gridDataSource.data.indexOf(user, 0), 1); + user_ids.push(user.id()) + }); + this.pcrud.remove(users).subscribe(user => { + this.pcrud.autoApply(user).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)); + } + ); + }); + } + +} \ 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 index 2dd917f5b4..d7312a9b96 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 @@ -11,6 +11,10 @@ + + + +
+ +
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 91c4b2813f..ebde77643e 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 @@ -16,6 +16,9 @@ import {ToastService} from '@eg/share/toast/toast.service'; import {CourseAssociateMaterialComponent } from './course-associate-material.component'; +import {CourseAssociateUsersComponent + } from './course-associate-users.component'; + @Component({ templateUrl: './course-list.component.html' }) @@ -34,6 +37,9 @@ export class CourseListComponent implements OnInit { @ViewChild('archiveSuccessString', { static: true }) archiveSuccessString: StringComponent; @ViewChild('courseMaterialDialog', {static: true}) private courseMaterialDialog: CourseAssociateMaterialComponent; + @ViewChild('courseUserDialog', {static: true}) + private courseUserDialog: CourseAssociateUsersComponent; + @Input() sort_field: string; @Input() idl_class = "acmc"; @Input() dialog_size: 'sm' | 'lg' = 'lg'; @@ -79,7 +85,7 @@ export class CourseListComponent implements OnInit { limit: pager.limit, order_by: orderBy }; - return this.pcrud.retrieveAll(this.idl_class, searchOps, {fleshSelectors: true}); + return this.pcrud.retrieveAll(this.idl_class, searchOps, {fleshSelectors: true}) }; } @@ -187,6 +193,41 @@ export class CourseListComponent implements OnInit { }); } + /** + * Uses the course id to fetch the different users associated with that course. + * @param course The course id + * @param currentMaterials + */ + fetchCourseUsers(course, currentMaterials): Promise { + return new Promise((resolve, reject) => { + this.pcrud.search('acmcu', {course: course}).subscribe(res => { + if(res) this.fleshUserDetails(res.usr(), res.usr_role()); + }, err => { + reject(err); + }, () => resolve(this.courseUserDialog.gridDataSource.data)); + }); + } + + /** + * Takes the user id from the course table, and cross references that with the user table, + * to find the right data. + * @param userId The user id that is to be cross referenced. + * @param usr_role The user role that is to be added to the grid. + */ + fleshUserDetails(userId, usr_role) { + return new Promise((resolve, reject) => { + this.pcrud.search("au", {id:userId}).subscribe(res => { + if (res) { + let user = res; + user._usr_role = usr_role; + this.courseUserDialog.gridDataSource.data.push(user); + } + }, err => { + reject(err); + }, () => resolve(this.courseMaterialDialog.gridDataSource.data)); + }); + } + fleshItemDetails(itemId, relationship): Promise { return new Promise((resolve, reject) => { this.net.request( @@ -219,5 +260,21 @@ export class CourseListComponent implements OnInit { }); }); } + + /** + * Opens the user dialog component using the course id + * @param course + */ + openUsersDialog(course) { + let currentUsers = [] + this.courseUserDialog.gridDataSource.data = []; + this.fetchCourseUsers(course[0].id(), currentUsers).then(res => { + this.courseUserDialog.currentCourse = course[0]; + this.courseUserDialog.users = currentUsers; + this.courseUserDialog.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 index 180faca887..3823648afe 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 @@ -5,6 +5,7 @@ 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 {CourseAssociateUsersComponent} from './course-associate-users.component'; import {CourseReservesRoutingModule} from './routing.module'; import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-location-select.module'; @@ -12,7 +13,8 @@ import {ItemLocationSelectModule} from '@eg/share/item-location-select/item-loca declarations: [ CourseListComponent, CoursePageComponent, - CourseAssociateMaterialComponent + CourseAssociateMaterialComponent, + CourseAssociateUsersComponent ], imports: [ StaffCommonModule, 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 edeeed3e0d..de946c42d9 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 @@ -170,6 +170,31 @@ export class CourseService { }); } + disassociateUsers(user) { + return new Promise((resolve, reject) => { + let user_ids = []; + let course_library_hash = {}; + user.forEach(course => { + user_ids.push(course.id()); + course_library_hash[course.id()] = course.owning_lib(); + }); + this.pcrud.search('acmcu', {user: user_ids}).subscribe(user => { + user.course(user_ids); + this.pcrud.autoApply(user).subscribe(res => { + console.log(res); + }, err => { + reject(err); + }, () => { + resolve(user); + }); + }, err => { + reject(err) + }, () => { + resolve(user_ids); + }); + }); + } + resetItemFields(material, course_lib) { this.pcrud.retrieve('acp', material.item(), {flesh: 3, flesh_fields: {acp: ['call_number']}}).subscribe(copy => { -- 2.43.2