import {IdlObject} from '@eg/core/idl.service';
import {BasketService} from '@eg/share/catalog/basket.service';
+interface BrowsePage {
+ leftPivot: number;
+ rightPivot: number;
+ entries: any[];
+}
+
@Component({
selector: 'eg-catalog-browse-pager',
templateUrl: 'browse-pager.component.html'
this.fetchPageData().then(_ => this.setPrevNext());
}
- fetchPageData(): Promise<any> {
+ pageEntryId(): number {
+ return Number(
+ this.searchContext.termSearch.hasBrowseEntry.split(',')[0]
+ );
+ }
- let found = false;
- const mbeId = this.pageEntryId();
- this.staffCat.browsePagerResults.forEach(result => {
- if (result.browse_entry === mbeId) {
- found = true;
- }
+ getEntryPageIndex(mbeId: number): number {
+ let idx = null;
+ this.staffCat.browsePagerData.forEach((page, index) => {
+ page.entries.forEach(entry => {
+ if (entry.browse_entry === mbeId) {
+ idx = index;
+ }
+ });
});
+ return idx;
+ }
+
- if (found) {
+ getEntryPage(mbeId: number): BrowsePage {
+ return this.staffCat.browsePagerData[this.getEntryPageIndex(mbeId)];
+ }
+
+ fetchPageData(): Promise<any> {
+
+ if (this.getEntryPage(this.pageEntryId())) {
+ // We have this page's data already
return Promise.resolve();
- } else {
- return this.fetchBrowseData(null);
}
+
+ return this.fetchBrowsePage(null);
}
// Grab a page of browse results
- fetchBrowseData(prev: boolean): Promise<any> {
+ fetchBrowsePage(prev: boolean): Promise<any> {
const ctx = this.searchContext.clone();
ctx.pager.limit = this.searchContext.pager.limit;
ctx.termSearch.hasBrowseEntry = null; // avoid term search
if (prev !== null) {
- ctx.browseSearch.pivot = this.getBoundaryPivot(prev);
+ const page = this.getEntryPage(this.pageEntryId());
+ const pivot = prev ? page.leftPivot : page.rightPivot;
+ if (pivot === null) {
+ console.debug('Browse has reached the end of the rainbow');
+ return;
+ }
+ ctx.browseSearch.pivot = pivot;
}
const results = [];
return this.cat.browse(ctx)
.pipe(tap(result => results.push(result)))
.toPromise().then(_ => {
+ if (results.length === 0) { return; }
+
+ // At the end of the data set, final pivots are not present
+ let leftPivot = null;
+ let rightPivot = null;
+ if (results[0].pivot_point) {
+ leftPivot = results.shift().pivot_point;
+ }
+ if (results[results.length - 1].pivot_point) {
+ rightPivot = results.pop().pivot_point;
+ }
+
+ // We only care about entries with bib record sources
+ let keepEntries = results.filter(e => Boolean(e.sources))
+
+ if (leftPivot === null || rightPivot === null) {
+ // When you reach the edge of the data set, you can get
+ // the same browse entries from different API calls.
+ // From what I can tell, the last page will always have
+ // 5 entries, even if you've already seen some of those
+ // entries. Trim the dupes since they affect the logic.
+ const keep = [];
+ keepEntries.forEach(e => {
+ if (!this.getEntryPage(e.browse_entry)) {
+ keep.push(e);
+ }
+ });
+ keepEntries = keep;
+ }
+
+ const page: BrowsePage = {
+ leftPivot: leftPivot,
+ rightPivot: rightPivot,
+ entries: keepEntries
+ };
+
if (prev) {
- this.staffCat.browsePagerResults =
- results.concat(this.staffCat.browsePagerResults);
+ this.staffCat.browsePagerData.unshift(page);
} else {
- this.staffCat.browsePagerResults =
- this.staffCat.browsePagerResults.concat(results);
+ this.staffCat.browsePagerData.push(page);
}
this.browseLoading = false;
});
}
- pageEntryId(): number {
- return Number(
- this.searchContext.termSearch.hasBrowseEntry.split(',')[0]
- );
- }
-
// Collect enough browse data to display previous, current, and
// next heading. This can mean fetching an additional page of data.
- setPrevNext(take: number = 1): Promise<any> {
+ setPrevNext(take2: boolean = false): Promise<any> {
- // Should never have to call this more than 3 times, with the
- // first 2 collecting data and the final assing prev/next.
- if (take > 3) { return Promise.resolve(); }
-
- let pageEntry, previous: any;
+ let previous: any;
const mbeId = this.pageEntryId();
- this.staffCat.browsePagerResults.forEach(result => {
- // ignore pivot and authority-only entries
- if (!result.sources) { return; }
-
- if (result.browse_entry === mbeId) {
- pageEntry = result;
- }
+ this.staffCat.browsePagerData.forEach(page => {
+ page.entries.forEach(entry => {
- if (previous) {
- if (result.browse_entry === mbeId) {
- this.prevEntry = previous;
+ if (previous) {
+ if (entry.browse_entry === mbeId) {
+ this.prevEntry = previous;
+ }
+ if (previous.browse_entry === mbeId) {
+ this.nextEntry = entry;
+ }
}
- if (previous.browse_entry === mbeId) {
- this.nextEntry = result;
- }
- }
- previous = result;
+ previous = entry;
+ });
});
+ if (take2) {
+ // If we have to call this more than twice it means we've
+ // reached the boundary of the full data set and there's
+ // no more data to fetch.
+ return Promise.resolve();
+ }
+
let promise;
- if (!pageEntry) {
- promise = this.fetchBrowseData(null)
- } else if (!this.prevEntry) {
- promise = this.fetchBrowseData(true);
+ if (!this.prevEntry) {
+ promise = this.fetchBrowsePage(true);
} else if (!this.nextEntry) {
- promise = this.fetchBrowseData(false);
+ promise = this.fetchBrowsePage(false);
}
if (promise) {
- return promise.then(_ => this.setPrevNext(take + 1));
+ return promise.then(_ => this.setPrevNext(true));
}
return Promise.resolve();
}
- getBoundaryPivot(prev?: boolean): number {
- const results = this.staffCat.browsePagerResults;
- return prev ? results[0].pivot_point :
- results[results.length - 1].pivot_point;
- }
-
setSearchPivot(prev?: boolean) {
// When traversing browse result page boundaries, modify the
// search pivot to keep up.
- const mbeId = Number( // for this page
- this.searchContext.termSearch.hasBrowseEntry.split(',')[0]);
-
const targetMbe = Number(
- prev ? this.prevEntry.browse_entry : this.nextEntry.browse_entry
+ prev ? this.prevEntry.browse_entry : this.nextEntry.browse_entry
);
- let results = [].concat(this.staffCat.browsePagerResults);
- if (prev) { results = results.reverse(); }
-
- let current;
- let lastPivot = null;
- let lastWasPivot = false;
- let done = false;
- results.forEach(result => {
- if (done) { return; }
- const entryId = Number(result.browse_entry || -1);
-
- // Pivots will be back-to-back in the full results set
- // We only care about the first pivot encountered in a
- // 2-pivot cluster.
- if (result.pivot_point && !lastWasPivot) {
- lastPivot = result.pivot_point;
- lastWasPivot = true;
- return;
- }
+ const curPageIdx = this.getEntryPageIndex(this.pageEntryId());
+ const targetPageIdx = this.getEntryPageIndex(targetMbe);
- lastWasPivot = false;
+ if (targetPageIdx !== curPageIdx) {
+ // We are crossing a page boundary
- if (current) {
+ const curPage = this.getEntryPage(this.pageEntryId());
- if (entryId === targetMbe && lastPivot) {
- this.searchContext.browseSearch.pivot = lastPivot;
- done = true;
- }
- } else if (entryId === mbeId) {
- current = result;
+ if (prev) {
+ this.searchContext.browseSearch.pivot = curPage.leftPivot;
+
+ } else {
+ this.searchContext.browseSearch.pivot = curPage.rightPivot;
}
- });
+ }
}
// Find the browse entry for the next/prev page and navigate there