lp1849212 Angular Catalog Show Link to Course
authorKyle Huckins <khuckins@catalyte.io>
Mon, 25 Nov 2019 22:06:04 +0000 (22:06 +0000)
committerKyle Huckins <khuckins@catalyte.io>
Tue, 3 Dec 2019 18:29:16 +0000 (18:29 +0000)
- Add a column retrieving the names of courses linked to materials
when opted into the Course Reserves functionality.
- Expand the bib record summary when opted in to display all courses
associated with an item.

 Changes to be committed:
modified:   Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts
modified:   Open-ILS/src/eg2/src/app/staff/catalog/record/copies.component.html
modified:   Open-ILS/src/eg2/src/app/staff/catalog/record/copies.component.ts
modified:   Open-ILS/src/eg2/src/app/staff/common.module.ts
modified:   Open-ILS/src/eg2/src/app/staff/share/bib-summary/bib-summary.component.html
modified:   Open-ILS/src/eg2/src/app/staff/share/bib-summary/bib-summary.component.ts
modified:   Open-ILS/src/eg2/src/app/staff/share/course.service.ts

Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts
Open-ILS/src/eg2/src/app/staff/catalog/record/copies.component.html
Open-ILS/src/eg2/src/app/staff/catalog/record/copies.component.ts
Open-ILS/src/eg2/src/app/staff/common.module.ts
Open-ILS/src/eg2/src/app/staff/share/bib-summary/bib-summary.component.html
Open-ILS/src/eg2/src/app/staff/share/bib-summary/bib-summary.component.ts
Open-ILS/src/eg2/src/app/staff/share/course.service.ts

index 64bd5dc..0ca63cf 100644 (file)
@@ -1,11 +1,11 @@
 import {NgModule} from '@angular/core';
 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 {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 '@eg/staff/share/course.service';
 
 @NgModule({
   declarations: [
@@ -13,6 +13,7 @@ import {CourseService} from '@eg/staff/share/course.service';
     CourseAssociateMaterialComponent
   ],
   imports: [
+    StaffCommonModule,
     AdminCommonModule,
     CourseReservesRoutingModule,
     ItemLocationSelectModule,
@@ -21,7 +22,6 @@ import {CourseService} from '@eg/staff/share/course.service';
   exports: [
   ],
   providers: [
-    CourseService
   ]
 })
 
index 7ee041f..1bacfe4 100644 (file)
   <span *ngIf="!context.holdable(copy)" i18n>No</span>
 </ng-template>
 
+<ng-template #courseTemplate let-copy="row">
+  <div *ngFor="let course of copy._courses">{{course.course_number()}}</div>
+</ng-template>
+
 <div class='eg-copies w-100 mt-3'>
   <eg-grid #copyGrid [dataSource]="gridDataSource" 
     [disableSelect]="true"
@@ -62,6 +66,9 @@
     <eg-grid-column i18n-label label="Holdable?" name="holdable" 
       [cellTemplate]="holdableTemplate" [cellContext]="copyContext">
     </eg-grid-column>
+    <eg-grid-column i18n-label label="Course" name="course"
+      [cellTemplate]="courseTemplate" *ngIf="usingCourseModule">
+    </eg-grid-column>
     <eg-grid-column i18n-label label="Status" path="copy_status">
     </eg-grid-column>
     <eg-grid-column i18n-label label="Due Date" path="due_date" datatype="timestamp">
index 24350d8..b08a2c5 100644 (file)
@@ -7,6 +7,7 @@ import {Pager} from '@eg/share/util/pager';
 import {OrgService} from '@eg/core/org.service';
 import {GridDataSource} from '@eg/share/grid/grid';
 import {GridComponent} from '@eg/share/grid/grid.component';
+import {CourseService} from '@eg/staff/share/course.service';
 
 @Component({
   selector: 'eg-catalog-copies',
@@ -16,6 +17,7 @@ export class CopiesComponent implements OnInit {
 
     recId: number;
     initDone = false;
+    usingCourseModule = false;
     gridDataSource: GridDataSource;
     copyContext: any; // grid context
     @ViewChild('copyGrid', { static: true }) copyGrid: GridComponent;
@@ -30,6 +32,7 @@ export class CopiesComponent implements OnInit {
     }
 
     constructor(
+        private course: CourseService,
         private net: NetService,
         private org: OrgService,
         private staffCat: StaffCatalogService,
@@ -39,6 +42,9 @@ export class CopiesComponent implements OnInit {
 
     ngOnInit() {
         this.initDone = true;
+        this.course.isOptedIn().then(res => {
+            this.usingCourseModule = res;
+        });
 
         this.gridDataSource.getRows = (pager: Pager, sort: any[]) => {
             // sorting not currently supported
@@ -81,6 +87,13 @@ export class CopiesComponent implements OnInit {
             pager.offset,
             this.staffCat.prefOrg ? this.staffCat.prefOrg.id() : null
         ).pipe(map(copy => {
+            this.org.settings('circ.course_materials_opt_in').then(res => {
+                if (res['circ.course_materials_opt_in']) {
+                    this.course.getCoursesFromMaterial(copy.id).then(courseList => {
+                        copy._courses = courseList;
+                    });
+                }
+            });
             copy.active_date = copy.active_date || copy.create_date;
             return copy;
         }));
index c0fe41b..442254a 100644 (file)
@@ -16,6 +16,7 @@ import {DatetimeValidatorDirective} from '@eg/share/validators/datetime_validato
 import {MultiSelectComponent} from '@eg/share/multi-select/multi-select.component';
 import {NotBeforeMomentValidatorDirective} from '@eg/share/validators/not_before_moment_validator.directive';
 import {PatronBarcodeValidatorDirective} from '@eg/share/validators/patron_barcode_validator.directive';
+import {CourseService} from './share/course.service'
 
 /**
  * Imports the EG common modules and adds modules common to all staff UI's.
@@ -66,7 +67,8 @@ export class StaffCommonModule {
             ngModule: StaffCommonModule,
             providers: [ // Export staff-wide services
                 AccessKeyService,
-                AudioService
+                AudioService,
+                CourseService
             ]
         };
     }
index 45345d2..a1a6bb4 100644 (file)
               <div class="flex-1">{{summary.record.edit_date() | date:'short'}}</div>
             </div>
           </li>
+          <ng-container *ngIf="expand && has_course">
+            <li class="list-group-item">
+              <div class="d-flex">
+                <div class="flex-1 font-weight-bold" i18n>Associated Courses</div>
+              </div>
+            </li>
+            <li class="list-group-item" *ngFor="let course of courses">
+              <div class="d-flex">
+                <div class="flex-1 font-weight-bold" i18n>Course Name:</div>
+                <div class="flex-3">{{course.name()}}</div>
+                <div class="flex-1 font-weight-bold" i18n>Course Number:</div>
+                <div class="flex-1">{{course.course_number()}}</div>
+                <div class="flex-1 font-weight-bold" i18n>Section Number:</div>
+                <div class="flex-1">{{course.section_number()}}</div>
+                <div class="flex-1 font-weight-bold" i18n>Owning Library:</div>
+                <div class="flex-1">{{this.org.get(course.owning_lib()).shortname()}}</div>
+              </div>
+            </li>
+          </ng-container>
         </ul>
       </div>
     </div><!-- col -->
index 39b8944..edd73bf 100644 (file)
@@ -1,5 +1,6 @@
 import {Component, OnInit, Input} from '@angular/core';
 import {OrgService} from '@eg/core/org.service';
+import {CourseService} from '@eg/staff/share/course.service';
 import {BibRecordService, BibRecordSummary
     } from '@eg/share/catalog/bib-record.service';
 import {ServerStoreService} from '@eg/core/server-store.service';
@@ -13,6 +14,8 @@ import {CatalogService} from '@eg/share/catalog/catalog.service';
 export class BibSummaryComponent implements OnInit {
 
     initDone = false;
+    has_course = false;
+    courses: any;
 
     // True / false if the display is vertically expanded
     private _exp: boolean;
@@ -33,6 +36,7 @@ export class BibSummaryComponent implements OnInit {
         this.summary = s;
         if (this.initDone && this.summary) {
             this.summary.getBibCallNumber();
+            this.loadCourseInformation(this.summary.record.id());
         }
     }
 
@@ -40,13 +44,15 @@ export class BibSummaryComponent implements OnInit {
         private bib: BibRecordService,
         private org: OrgService,
         private store: ServerStoreService,
-        private cat: CatalogService
+        private cat: CatalogService,
+        private course: CourseService
     ) {}
 
     ngOnInit() {
 
         if (this.summary) {
             this.summary.getBibCallNumber();
+            this.loadCourseInformation(this.summary.record.id());
         } else {
             if (this.recordId) {
                 this.loadSummary();
@@ -63,6 +69,7 @@ export class BibSummaryComponent implements OnInit {
     }
 
     loadSummary(): void {
+        this.loadCourseInformation(this.recordId);
         this.bib.getBibSummary(this.recordId).toPromise()
         .then(summary => {
             summary.getBibCallNumber();
@@ -71,6 +78,19 @@ export class BibSummaryComponent implements OnInit {
         });
     }
 
+    loadCourseInformation(record_id) {
+        this.org.settings('circ.course_materials_opt_in').then(setting => {
+            if (setting['circ.course_materials_opt_in']) {
+                this.course.fetchCopiesInCourseFromRecord(record_id).then(course_list => {
+                    this.courses = course_list;
+                    this.has_course = true;
+                });
+            } else {
+                this.has_course = false;
+            }
+        });
+    }
+
     orgName(orgId: number): string {
         if (orgId) {
             return this.org.get(orgId).shortname();
index c8b60cc..cca2882 100644 (file)
@@ -1,9 +1,12 @@
+import {Injectable} from '@angular/core';
 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 {OrgService} from '@eg/core/org.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 
+@Injectable()
 export class CourseService {
 
     constructor(
@@ -11,9 +14,71 @@ export class CourseService {
         private evt: EventService,
         private idl: IdlService,
         private net: NetService,
+        private org: OrgService,
         private pcrud: PcrudService
     ) {}
 
+    isOptedIn(): Promise<any> {
+        return new Promise((resolve, reject) => {
+            this.org.settings('circ.course_materials_opt_in').then(res => {
+                resolve(res['circ.course_materials_opt_in']);
+            });
+        });
+    }
+    getCourses(course_ids?: Number[]): Promise<IdlObject[]> {
+        if (!course_ids) {
+            return this.pcrud.retrieveAll('acmc',
+                {}, {atomic: true}).toPromise();
+        } else {
+            return this.pcrud.search('acmc', {id: course_ids},
+                {}, {atomic: true}).toPromise();
+        }
+    }
+
+    getCoursesFromMaterial(copy_id): Promise<any> {
+        let id_list = [];
+        return new Promise((resolve, reject) => {
+
+            return this.pcrud.search('acmcm', {item: copy_id})
+            .subscribe(materials => {
+                if (materials) {
+                    id_list.push(materials.course());
+                }
+            }, err => {
+                console.log(err);
+                reject(err);
+            }, () => {
+                if (id_list.length) {
+                    return this.getCourses(id_list).then(courses => {
+                        resolve(courses);
+                    });
+                    
+                }
+            });
+        });
+    }
+
+    fetchCopiesInCourseFromRecord(record_id) {
+        let cp_list = [];
+        let course_list = [];
+        return new Promise((resolve, reject) => {
+            this.net.request(
+                'open-ils.cat',
+                'open-ils.cat.asset.copy_tree.global.retrieve',
+                this.auth.token(), record_id
+            ).subscribe(copy_tree => {
+                copy_tree.forEach(cn => {
+                    cn.copies().forEach(cp => {
+                        cp_list.push(cp.id());
+                    });
+                });
+            }, err => reject(err),
+            () => {
+                resolve(this.getCoursesFromMaterial(cp_list));
+            });
+        });
+    }
+
     disassociateMaterials(courses) {
         return new Promise((resolve, reject) => {
             let course_ids = [];