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: [
SearchFormComponent,
ResultRecordComponent,
ResultFacetsComponent,
- ResultPaginationComponent
+ ResultPaginationComponent,
+ RecordPaginationComponent
],
imports: [
EgStaffModule,
})
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,
) {}
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();
}
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,
--- /dev/null
+
+/* Bootstrap default is 20px */
+.pagination {margin: 0px 0px 0px 0px}
+
+
--- /dev/null
+<!--
+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>
--- /dev/null
+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 {
+ }
+
+}
+
+
<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>
) {}
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);
+ })
}
}
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';
searchContext: CatalogSearchContext;
constructor(
- private router: Router,
- private route: ActivatedRoute,
- private org: EgOrgService,
private pcrud: EgPcrudService,
private cat: EgCatalogService,
private staffCat: StaffCatalogService,
}
prevPage(): void {
- console.log('HERE');
this.searchContext.pager.decrement();
this.staffCat.search();
}
<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 || ' '}}
</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 || ' '}}
</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"/>
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({
searchContext: CatalogSearchContext;
constructor(
+ private router: Router,
private org: EgOrgService,
private net: EgNetService,
private cat: EgCatalogService,
+ private catUrl: EgCatalogUrlService,
private staffCat: StaffCatalogService
) {}
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});
+ }
+
}
*/
+/** 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;
}