LP#626157 Ang2 experiments
authorBill Erickson <berickxx@gmail.com>
Sat, 9 Dec 2017 15:57:59 +0000 (10:57 -0500)
committerBill Erickson <berickxx@gmail.com>
Mon, 11 Dec 2017 17:39:51 +0000 (12:39 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
12 files changed:
Open-ILS/webby-src/src/app/staff/catalog/catalog.module.ts
Open-ILS/webby-src/src/app/staff/catalog/record/copies.component.ts
Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.css [new file with mode: 0644]
Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.html [new file with mode: 0644]
Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.ts [new file with mode: 0644]
Open-ILS/webby-src/src/app/staff/catalog/record/record.component.html
Open-ILS/webby-src/src/app/staff/catalog/record/record.component.ts
Open-ILS/webby-src/src/app/staff/catalog/record/record.service.ts
Open-ILS/webby-src/src/app/staff/catalog/result/pagination.component.ts
Open-ILS/webby-src/src/app/staff/catalog/result/record.component.html
Open-ILS/webby-src/src/app/staff/catalog/result/record.component.ts
Open-ILS/webby-src/src/styles.css

index 8c4176c..420d271 100644 (file)
@@ -16,6 +16,7 @@ import {ResultFacetsComponent} from './result/facets.component';
 import {ResultRecordComponent} from './result/record.component';
 import {StaffCatalogService} from './staff-catalog.service';
 import {StaffRecordService} from './record/record.service';
+import {RecordPaginationComponent} from './record/pagination.component';
 
 @NgModule({
   declarations: [
@@ -27,7 +28,8 @@ import {StaffRecordService} from './record/record.service';
     SearchFormComponent,
     ResultRecordComponent,
     ResultFacetsComponent,
-    ResultPaginationComponent
+    ResultPaginationComponent,
+    RecordPaginationComponent
   ],
   imports: [
     EgStaffModule,
index 0af98a5..4dd4c90 100644 (file)
@@ -12,9 +12,17 @@ import {EgOrgService} from '@eg/core/org';
 })
 export class CopiesComponent implements OnInit {
 
-    @Input() recordId: number;
     pager: Pager;
     copies: any[];
+    recId: number;
+    initDone: boolean = false;
+
+    @Input() set recordId(id: number) {
+        this.recId = id;
+        // Only force new data collection when recordId()
+        // is invoked after ngInit() has already run.
+        if (this.initDone) this.collectData();
+    }
 
     constructor(
         private net: EgNetService,
@@ -24,9 +32,14 @@ export class CopiesComponent implements OnInit {
     ) {}
 
     ngOnInit() { 
-        if (!this.recordId) return;
+        this.initDone = true;
+        this.collectData();
+    }
+
+    collectData() {
+        if (!this.recId) return;
         this.pager = new Pager();
-        this.pager.limit = 10; // TODO
+        this.pager.limit = 10; // TODO UI
         this.fetchCopies();
     }
 
@@ -39,7 +52,7 @@ export class CopiesComponent implements OnInit {
         this.net.request(
             'open-ils.search',
             'open-ils.search.bib.copies.staff',
-            this.recordId,
+            this.recId,
             this.staffCat.searchContext.searchOrg.id(),
             this.staffCat.searchContext.searchOrg.ou_type().depth(), // TODO
             this.pager.limit,
diff --git a/Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.css b/Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.css
new file mode 100644 (file)
index 0000000..262903d
--- /dev/null
@@ -0,0 +1,5 @@
+
+/* Bootstrap default is 20px */
+.pagination {margin: 0px 0px 0px 0px}
+
+
diff --git a/Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.html b/Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.html
new file mode 100644 (file)
index 0000000..cc89f43
--- /dev/null
@@ -0,0 +1,44 @@
+<!-- 
+Using bare BS pagination instead of ng-bootstrap, which seemed 
+unnecessary given we have to track paging externally anyway.
+-->
+<span>current index = {{index}}</span>
+<ul class="pagination">
+  <li class="page-item">
+    <a class="no-href page-link" 
+      i18n-aria-label aria-label="Start"
+      (click)="firstRecord()">
+      <span i18n>Start</span>
+    </a>
+  </li>
+  <li class="page-item">
+    <a class="no-href page-link" 
+      i18n-aria-label aria-label="Previous"
+      (click)="prevRecord()">
+      <span i18n>Previous</span>
+    </a>
+  </li>
+  <li class="page-item">
+    <a class="no-href page-link" 
+      i18n-aria-label aria-label="Next"
+      (click)="nextRecord()">
+      <span i18n>Next</span>
+    </a>
+  </li>
+  <li class="page-item">
+    <a class="no-href page-link" 
+      i18n-aria-label aria-label="End"
+      (click)="lastRecord()">
+      <span i18n>End</span>
+    </a>
+  </li>
+  <li class="page-item">
+    <a class="no-href page-link" 
+      i18n-aria-label aria-label="Back to Results"
+      (click)="returnToSearch()">
+      <span i18n>
+        Back to Results ({{index}} / {{searchContext.result.cout}})
+      </span>
+    </a>
+  </li>
+</ul>
diff --git a/Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.ts b/Open-ILS/webby-src/src/app/staff/catalog/record/pagination.component.ts
new file mode 100644 (file)
index 0000000..45347c4
--- /dev/null
@@ -0,0 +1,119 @@
+import {Component, OnInit, Input} from '@angular/core';
+import {Router} from '@angular/router';
+import {EgCatalogService} from '@eg/share/catalog/catalog.service';
+import {CatalogSearchContext} from '@eg/share/catalog/search-context';
+import {EgCatalogUrlService} from '@eg/share/catalog/catalog-url.service';
+import {StaffCatalogService} from '../staff-catalog.service';
+import {StaffRecordService} from './record.service';
+
+
+@Component({
+  selector: 'eg-catalog-record-pagination',
+  styleUrls: ['pagination.component.css'],
+  templateUrl: 'pagination.component.html'
+})
+export class RecordPaginationComponent implements OnInit {
+
+    searchContext: CatalogSearchContext;
+    index: number = 0;
+    id: number;
+    initDone: boolean = false;
+
+    @Input() set recordId(id: number) {
+        this.id = id;
+        // Only apply new record data after the initial load
+        if (this.initDone) this.setIndex();
+    }
+
+    constructor(
+        private router: Router,
+        private cat: EgCatalogService,
+        private catUrl: EgCatalogUrlService,
+        private staffCat: StaffCatalogService,
+        private staffRecord: StaffRecordService
+    ) {}
+
+    ngOnInit() { 
+        this.initDone = true;
+        this.setIndex();
+    }
+
+    firstRecord(): void {
+    }
+
+    lastRecord(): void {
+    }
+
+    nextRecord(): void {
+        this.findRecordAtIndex(this.index + 1).then(id => {
+            let params = this.catUrl.toUrlParams(this.searchContext);
+            this.router.navigate(
+                ['/staff/catalog/record/' + id], {queryParams: params});
+        });
+    }
+
+    prevRecord(): void {
+        this.findRecordAtIndex(this.index - 1)
+        .then(id => {
+            // navigate to record
+            // teach record.component to update record w/ route navigation!
+        });
+    }
+
+    returnToSearch(): void {
+    }
+
+
+    // Returns the offset of the record within the search results as a whole.
+    searchIndex(idx: number): number {
+        return idx + this.searchContext.pager.offset;
+    }
+
+    setIndex(): Promise<void> {
+        this.searchContext = this.staffCat.searchContext;
+        this.index = null;
+
+        return new Promise((resolve, reject) => {
+
+            // First see if the select record sits in the current page
+            // of search results.  This will be the common case.
+            this.searchContext.result.records.forEach((rec, idx) => {
+                if (rec.id == this.id) {
+                    this.index = this.searchIndex(idx)
+                    resolve();
+                }
+            });
+
+            if (this.index !== null) return;
+
+            // Record not found in current page of search results.
+            // Re-run the search with a broad range to see if we
+            // can track it down.
+            reject('no search index found for record ' + this.id);
+        });
+    }
+
+    findRecordAtIndex(index: number): Promise<number> {
+
+        // First see if the select record sits in the current page
+        // of search results.  
+        return new Promise((resolve, reject) => {
+
+            // See if the record is avaialable in the current search page.
+            this.searchContext.result.records.forEach((rec, idx) => {
+                if (this.searchIndex(idx) == index) {
+                    resolve(rec.id);
+                }
+            });
+
+            // Otherwise, expand the search
+            reject('no record found at index ' + index);
+        });
+    }
+
+    navigatToRecord(): void {
+    }
+
+}
+
+
index 3d10950..c04998b 100644 (file)
@@ -1,8 +1,15 @@
 
 <div id="staff-catalog-record-container">
-  <div id='staff-catalog-bib-summary-container'>
-  <eg-bib-summary [bibSummary]="staffRecord.bibSummary">
-  </eg-bib-summary>
+  <div id='staff-catalog-bib-navigation'>
+    <div *ngIf="searchContext.result.records">
+      <eg-catalog-record-pagination [recordId]="recordId">
+      </eg-catalog-record-pagination>
+    </div>
+  </div>
+  <div id='staff-catalog-bib-summary-container' class='mt-1'>
+    <eg-bib-summary [bibSummary]="staffRecord.bibSummary">
+    </eg-bib-summary>
+  </div>
   <div id='staff-catalog-copies-container' class='mt-3'>
     <eg-catalog-copies [recordId]="recordId"></eg-catalog-copies>
   </div>
index f7f7af8..1c0558c 100644 (file)
@@ -26,9 +26,13 @@ export class RecordComponent implements OnInit {
     ) {}
 
     ngOnInit() { 
-        this.recordId = +this.route.snapshot.paramMap.get('id');
         this.searchContext = this.staffCat.searchContext;
-        this.staffRecord.setRecord(this.recordId);
+
+        // Watch for URL record ID changes
+        this.route.paramMap.subscribe((params: ParamMap) => {
+            this.recordId = +params.get('id');
+            this.staffRecord.setRecord(this.recordId);
+        })
     }
 }
 
index 224ba06..fcd80cd 100644 (file)
@@ -1,6 +1,4 @@
 import {Injectable} from '@angular/core';
-import {Router, ActivatedRoute} from '@angular/router';
-import {EgOrgService} from '@eg/core/org';
 import {EgCatalogService} from '@eg/share/catalog/catalog.service';
 import {EgCatalogUrlService} from '@eg/share/catalog/catalog-url.service';
 import {CatalogSearchContext} from '@eg/share/catalog/search-context';
@@ -19,9 +17,6 @@ export class StaffRecordService {
     searchContext: CatalogSearchContext;
 
     constructor(
-        private router: Router,
-        private route: ActivatedRoute,
-        private org: EgOrgService,
         private pcrud: EgPcrudService,
         private cat: EgCatalogService,
         private staffCat: StaffCatalogService,
index ff1746c..917491d 100644 (file)
@@ -27,7 +27,6 @@ export class ResultPaginationComponent implements OnInit {
     }
 
     prevPage(): void {
-        console.log('HERE');
         this.searchContext.pager.decrement();
         this.staffCat.search();
     }
index 1bc7c31..a9268bc 100644 (file)
@@ -20,7 +20,8 @@
           <span class="font-weight-light font-italic">
             #{{index + 1 + searchContext.pager.offset}}
           </span>
-          <a href='javascript:;' routerLink="/staff/catalog/record/{{bibSummary.id}}">
+          <a href="javascript:void(0)"
+            (click)="navigatToRecord(bibSummary.id)">
             {{bibSummary.title || '&nbsp;'}}
           </a>
         </div>
       <div class="row pt-2">
         <div class="col-12">
           <!-- nbsp allows the column to take shape when no value exists -->
-          <a href='javascript:;' 
-            (click)="searchAuthor(bibSummary)" style="font-style:italic">
+          <a href="javascript:void(0)"
+            (click)="searchAuthor(bibSummary)">
             {{bibSummary.author || '&nbsp;'}}
           </a>
         </div>
       </div>
       <div class="row pt-2">
         <div class="col-12">
-          <!--
-          <span>#{{index + 1 + searchContext.pager.offset}}</span>
-          -->
           <span>
             <img class="pad-right-min"
               src="/images/format_icons/icon_format/{{bibSummary.ccvms.icon_format.code}}.png"/>
index b1bfde5..b7fc776 100644 (file)
@@ -1,8 +1,10 @@
 import {Component, OnInit, Input} from '@angular/core';
+import {Router} from '@angular/router';
 import {EgOrgService} from '@eg/core/org';
 import {EgCatalogService} from '@eg/share/catalog/catalog.service';
 import {CatalogSearchContext} from '@eg/share/catalog/search-context';
 import {EgNetService} from '@eg/core/net';
+import {EgCatalogUrlService} from '@eg/share/catalog/catalog-url.service';
 import {StaffCatalogService} from '../staff-catalog.service';
 
 @Component({
@@ -17,9 +19,11 @@ export class ResultRecordComponent implements OnInit {
     searchContext: CatalogSearchContext;
 
     constructor(
+        private router: Router,
         private org: EgOrgService,
         private net: EgNetService,
         private cat: EgCatalogService,
+        private catUrl: EgCatalogUrlService,
         private staffCat: StaffCatalogService
     ) {}
 
@@ -54,6 +58,16 @@ export class ResultRecordComponent implements OnInit {
         this.staffCat.search();
     }
 
+    /**
+     * Propagate the search params along when navigating to each record.
+     */
+    navigatToRecord(id: number) {
+        let params = this.catUrl.toUrlParams(this.searchContext);
+
+        this.router.navigate(
+          ['/staff/catalog/record/' + id], {queryParams: params});
+    }
+
 }
 
 
index b8dd531..3646a77 100644 (file)
@@ -5,21 +5,26 @@
 */
 
 
+/** BS default fonts are huge */
 body, .form-control, .btn {
   /* This more or less matches the font size of the angularjs client.
    * The default BS4 font of 1rem is comically large. 
    */
   font-size: .88rem;
 }
-
-/** BS default fonts are huge */
 h2 {font-size: 1.25rem}
 h3 {font-size: 1.15rem}
 h4 {font-size: 1.05rem}
 h5 {font-size: .95rem}
 
+
+/** Ang5 routes on clicks to href's with no values, so we can't have
+ * bare href's to force anchor styling.  Use this for anchors w/ no href.
+ * TODO: should we style all of them?  a:not([href]) ....
+ * */
 .no-href {
   cursor: pointer;
+  color: #007bff;
 }