holdCount: number;
bibCallNumber: string;
net: NetService;
+ displayHighlights: {[name: string]: string} = {};
constructor(record: IdlObject, orgId: number, orgDepth: number) {
this.id = Number(record.id());
})).toPromise();
}
+ fetchFieldHighlights(ctx: CatalogSearchContext): Promise<any> {
+
+ let hlMap;
+
+ // Extract the highlight map. Not all searches have them.
+ if ((hlMap = ctx.result) &&
+ (hlMap = hlMap.global_summary) &&
+ (hlMap = hlMap.query_struct) &&
+ (hlMap = hlMap.additional_data) &&
+ (hlMap = hlMap.highlight_map) &&
+ (Object.keys(hlMap).length > 0)) {
+ } else { return Promise.resolve(); }
+
+ return this.net.requestWithParamList(
+ 'open-ils.search',
+ 'open-ils.search.fetch.metabib.display_field.highlight',
+ [hlMap].concat(ctx.currentResultIds())
+ ).pipe(map(fields => {
+ if (fields.length === 0) { return; }
+
+ // Each 'fields' collection is an array of highlighted
+ // fields for a given bib record.
+ const summary =
+ ctx.result.records.filter(r => r.id === fields[0].source)[0];
+
+ fields.forEach(field => {
+ const dfMap = this.cmfMap[field.field].display_field_map();
+ if (!dfMap) { return; }
+ summary.displayHighlights[dfMap.name()] = field.highlight;
+ });
+ })).toPromise();
+ }
+
+
fetchFacets(ctx: CatalogSearchContext): Promise<void> {
if (!ctx.result) {
}
fetchCmfs(): Promise<void> {
- // At the moment, we only need facet CMFs.
if (Object.keys(this.cmfMap).length) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
this.pcrud.search('cmf',
- {facet_field : 't'}, {}, {atomic: true, anonymous: true}
+ {'-or': [{facet_field : 't'}, {display_field: 't'}]},
+ {flesh: 1, flesh_fields: {cmf: ['display_field_map']}},
+ {atomic: true, anonymous: true}
).subscribe(
cmfs => {
cmfs.forEach(c => this.cmfMap[c.id()] = c);
/**
- * Force the jacket image column to consume a consistent amount of
- * horizontal space, while allowing some room for the browser to
+ * Force the jacket image column to consume a consistent amount of
+ * horizontal space, while allowing some room for the browser to
* render the correct aspect ratio.
*/
.record-jacket-div {
max-height: 158px;
max-width: 100px;
}
+
+.oils_SH {
+ font-weight: bolder;
+ background-color: #99ff99;
+}
+
+.oils_SH.identifier {
+ font-weight: bolder;
+ background-color: #42b0f4;
+}
+
egDateFilter's
-->
+<ng-template #displayField let-field="field" let-summary="summary">
+ <ng-template #noHl>{{summary.display[field]}}</ng-template>
+ <ng-container *ngIf="summary.displayHighlights[field]; else noHl">
+ <span [innerHTML]="summary.displayHighlights[field]">
+ </span>
+ </ng-container>
+ <!--
+ <ng-container *ngIf="!summary.displayHighlights[field]">
+ {{summary.display[field]}}
+ </ng-container>
+ -->
+</ng-template>
+
<div class="col-lg-12 card tight-card mb-2 bg-light">
<div class="card-body">
<div class="row">
<ng-container *ngIf="!hasMrConstituentRecords(summary)">
<a routerLink="/staff/catalog/record/{{summary.id}}"
[queryParams]="currentParams()">
- {{summary.display.title || ' '}}
+ <ng-container
+ *ngTemplateOutlet="displayField;
+ context: {summary: summary, field: 'title'}">
+ </ng-container>
</a>
</ng-container>
</div>
<div class="col-lg-12">
<!-- nbsp allows the column to take shape when no value exists -->
<a routerLink="/staff/catalog/search"
- [queryParams]="getAuthorSearchParams(summary)">
- {{summary.display.author || ' '}}
+ [queryParams]="getAuthorSearchParams(summary)">
+ <ng-container
+ *ngTemplateOutlet="displayField;
+ context: {summary: summary, field: 'author'}">
+ </ng-container>
</a>
</div>
</div>
</div>
</ng-container>
<ng-container *ngIf="summary.display.edition">
- <div class="pb-1" i18n>Edition: {{summary.display.edition}}</div>
+ <div class="pb-1" i18n>Edition:
+ <ng-container
+ *ngTemplateOutlet="displayField;
+ context: {summary: summary, field: 'edition'}">
+ </ng-container>
+ </div>
</ng-container>
<ng-container *ngIf="summary.display.publisher || summary.display.pubdate">
<!-- note publisher typically includes pubdate -->
-import {Component, OnInit, OnDestroy, Input} from '@angular/core';
+import {Component, OnInit, OnDestroy, Input, ViewEncapsulation} from '@angular/core';
import {Subscription} from 'rxjs';
import {Router, ParamMap} from '@angular/router';
import {OrgService} from '@eg/core/org.service';
@Component({
selector: 'eg-catalog-result-record',
templateUrl: 'record.component.html',
- styleUrls: ['record.component.css']
+ styleUrls: ['record.component.css'],
+ encapsulation: ViewEncapsulation.None // required for search highlighting
})
export class ResultRecordComponent implements OnInit, OnDestroy {
.then(ok => {
this.cat.fetchFacets(this.searchContext);
this.cat.fetchBibSummaries(this.searchContext)
- .then(ok2 => this.fleshSearchResults());
+ .then(_ =>
+ this.cat.fetchFieldHighlights(this.searchContext))
+ .then(_ => this.fleshSearchResults());
});
}
}