import {mergeMap} from 'rxjs/operators/mergeMap';
import {from} from 'rxjs/observable/from';
import {map} from 'rxjs/operators/map';
+import {tap} from 'rxjs/operators/tap';
import {OrgService} from '@eg/core/org.service';
import {UnapiService} from '@eg/share/catalog/unapi.service';
import {IdlService, IdlObject} from '@eg/core/idl.service';
compileMetabib(metabib: IdlObject,
orgId?: number, orgDepth?: number): Observable<BibRecordSummary> {
- const bibIds = metabib.source_maps().map(map => map.source());
+ // TODO: Create an API similar to the one that builds a combined
+ // mods blob for metarecords, except using display fields, etc.
+ // For now, this seems to get the job done.
+
+ // Non-master records
+ const relatedBibIds = metabib.source_maps()
+ .map(map => map.source())
+ .filter(id => id !== metabib.master_record());
+
let observer;
- const observable =
- new Observable<BibRecordSummary>(o => observer = o);
-
- let master;
- const summaries = [];
-
- // NOTE if we only need to augment with 'mattrs' it would be
- // faster to just grab those than to fetch the full bib-summary
- // for related records. Revisit.
-
- this.getBibSummary(bibIds, orgId, orgDepth).subscribe(
- sum => {
- summaries.push(sum);
- if (sum.id === Number(metabib.master_record())) {
- master = sum;
- master.metabibId = metabib.id();
- }
- },
- err => {},
- () => {
- summaries.forEach(sum => {
- if (sum.id !== master.id) {
- master.record.mattrs(
- master.record.mattrs().concat(sum.record.mattrs()))
- }
- });
+ const observable = new Observable<BibRecordSummary>(o => observer = o);
+
+ // NOTE: getBibSummary calls getHoldingsSummary against
+ // the bib record unnecessarily. It's called again below.
+ // Reconsider this approach (see also note above about API).
+ this.getBibSummary(metabib.master_record(), orgId, orgDepth)
+ .subscribe(summary => {
+ summary.metabibId = metabib.id();
- // Recompile attributes now that the data has been augmented
- master.compileRecordAttrs();
+ let promise;
+
+ if (relatedBibIds.length > 0) {
+
+ // Grab data for MR bib summary augmentation
+ promise = this.pcrud.search('mraf', {id: relatedBibIds})
+ .pipe(tap(attr => summary.record.mattrs().push(attr)))
+ .toPromise();
+ } else {
+
+ // Metarecord has only one constituent bib.
+ promise = Promise.resolve();
+ }
+
+ promise.then(() => {
+
+ // Re-compile with augmented data
+ summary.compileRecordAttrs();
// Fetch holdings data for the metarecord
this.getHoldingsSummary(metabib.id(), orgId, orgDepth, true)
.then(holdingsSummary => {
- master.holdingsSummary = holdingsSummary;
- observer.next(master);
+ summary.holdingsSummary = holdingsSummary;
+ observer.next(summary);
observer.complete();
});
- }
- );
+ });
+ });
return observable;
}
params.joinOp = [];
params.matchOp = [];
- ['format', 'available', 'hasBrowseEntry',
- 'date1', 'date2', 'dateOp', 'isMetarecord']
+ ['format', 'available', 'hasBrowseEntry', 'date1',
+ 'date2', 'dateOp', 'isMetarecord', 'fromMetarecord']
.forEach(field => {
if (ts[field]) {
params[field] = ts[field];
} else if (params.has('query')) {
// Scalars
- ['format', 'available', 'date1', 'date2', 'dateOp', 'isMetarecord']
+ ['format', 'available', 'date1', 'date2',
+ 'dateOp', 'isMetarecord', 'fromMetarecord']
.forEach(field => {
if (params.has(field)) {
ts[field] = params.get(field);
console.debug(`search query: ${fullQuery}`);
let method = 'open-ils.search.biblio.multiclass.query';
- if (ctx.termSearch.isSearchable() && ctx.termSearch.isMetarecord) {
+ if (ctx.termSearch.isSearchable()
+ && ctx.termSearch.isMetarecord
+ && !ctx.termSearch.fromMetarecord) {
method = 'open-ils.search.metabib.multiclass.query';
}
ctx.org.root().ou_type().depth() :
ctx.searchOrg.ou_type().depth();
+ // Term search, looking for metarecords, but no
+ // specific metarecord has been selected for display.
const isMeta = (
ctx.termSearch.isSearchable() &&
- ctx.termSearch.isMetarecord
+ ctx.termSearch.isMetarecord &&
+ !ctx.termSearch.fromMetarecord
);
let observable: Observable<BibRecordSummary>;
ccvmFilters: {[ccvmCode: string]: string[]};
facetFilters: FacetFilter[];
copyLocations: string[]; // ID's, but treated as strings in the UI.
+
+ // True when searching for metarecords
isMetarecord: boolean;
+
+ // Filter results by records which link to this metarecord ID.
+ fromMetarecord: number;
+
hasBrowseEntry: string; // "entryId,fieldId"
date1: number;
date2: number;
this.date1 = null;
this.date2 = null;
this.dateOp = 'is';
+ this.fromMetarecord = null;
// Apply empty string values for each ccvm filter
this.ccvmFilters = {};
return (
this.query[0] !== ''
|| this.hasBrowseEntry !== ''
+ || this.fromMetarecord !== null
);
}
str += ` has_browse_entry(${ts.hasBrowseEntry})`;
}
+ if (ts.fromMetarecord) {
+ str += ` from_metarecord(${ts.fromMetarecord})`;
+ }
+
if (ts.format) {
str += ' format(' + ts.format + ')';
}
<div class="col-lg-12 font-weight-bold">
<!-- nbsp allows the column to take shape when no value exists -->
<a href="javascript:void(0)"
- (click)="navigatToRecord(summary.id)">
+ (click)="navigatToRecord(summary)">
{{summary.display.title || ' '}}
</a>
</div>
<div class="float-right">
<span>
<button (click)="placeHold()"
+ [disabled]="summary.metabibId"
class="btn btn-sm btn-success label-with-material-icon small-text-1">
<span class="material-icons">check</span>
<span i18n>Place Hold</span>
/**
* Propagate the search params along when navigating to each record.
*/
- navigatToRecord(id: number) {
+ navigatToRecord(summary: BibRecordSummary) {
const params = this.catUrl.toUrlParams(this.searchContext);
+ if (summary.metabibId) {
+ this.searchContext.termSearch.fromMetarecord = summary.metabibId;
+ this.staffCat.search();
+ return;
+ }
+
this.router.navigate(
- ['/staff/catalog/record/' + id], {queryParams: params});
+ ['/staff/catalog/record/' + summary.id], {queryParams: params});
}
toggleBasketEntry() {
this.context.browseSearch.reset();
this.context.identSearch.reset();
this.context.termSearch.hasBrowseEntry = '';
+ this.context.termSearch.fromMetarecord = null;
this.staffCat.search();
break;