LPXXX Ang catalog search highlighting user/berick/lpxxx-ang-cat-search-highlight
authorBill Erickson <berickxx@gmail.com>
Thu, 16 Jan 2020 21:22:04 +0000 (16:22 -0500)
committerBill Erickson <berickxx@gmail.com>
Thu, 16 Jan 2020 21:22:04 +0000 (16:22 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/share/catalog/bib-record.service.ts
Open-ILS/src/eg2/src/app/share/catalog/catalog.service.ts
Open-ILS/src/eg2/src/app/staff/catalog/catalog.service.ts
Open-ILS/src/eg2/src/app/staff/catalog/result/record.component.html
Open-ILS/src/eg2/src/app/staff/catalog/result/record.component.ts

index 465a0af..83d66c0 100644 (file)
@@ -31,7 +31,7 @@ export class BibRecordSummary {
     holdCount: number;
     bibCallNumber: string;
     net: NetService;
-    displayHighlights: {[name: string]: string} = {};
+    displayHighlights: {[name: string]: string | string[]} = {};
 
     constructor(record: IdlObject, orgId: number, orgDepth: number) {
         this.id = Number(record.id());
index cbc89c9..ffc8d9c 100644 (file)
@@ -228,10 +228,19 @@ export class CatalogService {
             (Object.keys(hlMap).length > 0)) {
         } else { return Promise.resolve(); }
 
-        return this.net.requestWithParamList(
+        // Returns bib IDs or metabib IDs depending on the search type.
+        // If we have metabib IDs, map them to bib IDs for highlighting.
+        let ids = ctx.currentResultIds();
+        if (ctx.termSearch.groupByMetarecord) {
+            ids = ids.map(mrId =>
+                ctx.result.records.filter(r => mrId === r.metabibId)[0].id
+            );
+        }
+
+        return this.net.requestWithParamList( // API is list-based
             'open-ils.search',
             'open-ils.search.fetch.metabib.display_field.highlight',
-            [hlMap].concat(ctx.currentResultIds())
+            [hlMap].concat(ids)
         ).pipe(map(fields => {
             if (fields.length === 0) { return; }
 
@@ -240,15 +249,24 @@ export class CatalogService {
             const summary =
                 ctx.result.records.filter(r => r.id === fields[0].source)[0];
 
+            const highlights = summary.displayHighlights;
+
             fields.forEach(field => {
                 const dfMap = this.cmfMap[field.field].display_field_map();
                 if (!dfMap) { return; }
-                summary.displayHighlights[dfMap.name()] = field.highlight;
+
+                if (dfMap.multi() === 't') {
+                    if (!highlights[dfMap.name()]) {
+                        highlights[dfMap.name()] = [];
+                    }
+                    highlights[dfMap.name()].push(field.highlight);
+                } else {
+                    highlights[dfMap.name()] = field.highlight;
+                }
             });
         })).toPromise();
     }
 
-
     fetchFacets(ctx: CatalogSearchContext): Promise<void> {
 
         if (!ctx.result) {
index 86501fc..849e627 100644 (file)
@@ -61,7 +61,7 @@ export class StaffCatalogService {
         }
 
         if (!this.searchContext.pager.limit) {
-            this.searchContext.pager.limit = this.defaultSearchLimit || 20;
+            this.searchContext.pager.limit = this.defaultSearchLimit || 10;
         }
     }
 
index ee93fb0..8bfbb7a 100644 (file)
@@ -1,20 +1,13 @@
+
 <!-- 
-  TODO
-  routerLink's
-  egDateFilter's
+  Display the content for individual display fields
+  If join=true, join values with a comma
 -->
-
-<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-template #displayField let-field="field" let-join="join">
+  <ng-container *ngFor="let value of getDisplayValues(field); let first = first">
+    <ng-container *ngIf="join && !first">, </ng-container>
+    <span [innerHTML]="value"></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="flex-1 pl-2">
           <div class="row">
             <div class="col-lg-12 font-weight-bold">
-              <!-- nbsp allows the column to take shape when no value exists -->
               <ng-container *ngIf="hasMrConstituentRecords(summary)">
                   <a routerLink="/staff/catalog/search"
                     [queryParams]="appendFromMrParam(summary)">
-                    {{summary.display.title || '&nbsp;'}}
+                    <ng-container 
+                      *ngTemplateOutlet="displayField;context:{field: 'title'}">
+                    </ng-container>
                   </a>
               </ng-container>
               <ng-container *ngIf="!hasMrConstituentRecords(summary)">
                 <a routerLink="/staff/catalog/record/{{summary.id}}"
                   [queryParams]="currentParams()">
                   <ng-container 
-                    *ngTemplateOutlet="displayField; 
-                      context: {summary: summary, field: 'title'}">
+                    *ngTemplateOutlet="displayField;context:{field: 'title'}">
                   </ng-container>
                 </a>
               </ng-container>
@@ -83,8 +76,7 @@
               <a routerLink="/staff/catalog/search"
                 [queryParams]="getAuthorSearchParams(summary)">
                 <ng-container 
-                  *ngTemplateOutlet="displayField; 
-                    context: {summary: summary, field: 'author'}">
+                  *ngTemplateOutlet="displayField;context:{field: 'author'}">
                 </ng-container>
               </a>
             </div>
               <ng-container *ngIf="summary.display.physical_description">
                 <!-- [].concat() to avoid modifying the summary arrays -->
                 <div class="pb-1" i18n>Phys. Desc.: 
-                  {{[].concat(summary.display.physical_description).join(', ')}}
+                  <ng-container 
+                    *ngTemplateOutlet="displayField;context:{field: 'physical_description',join:true}">
+                  </ng-container>
                 </div>
               </ng-container>
               <ng-container *ngIf="summary.display.edition">
                 <div class="pb-1" i18n>Edition: 
                   <ng-container 
-                    *ngTemplateOutlet="displayField; 
-                      context: {summary: summary, field: 'edition'}">
+                    *ngTemplateOutlet="displayField;context:{field: 'edition'}">
                   </ng-container>
                 </div>
               </ng-container>
               <ng-container *ngIf="summary.display.publisher || summary.display.pubdate">
                 <!-- note publisher typically includes pubdate -->
                 <ng-container *ngIf="summary.display.publisher; else pubDate">
-                  <div class="pb-1" i18n>Publisher: {{summary.display.publisher}}</div>
+                  <div class="pb-1" i18n>Publisher:
+                    <ng-container 
+                      *ngTemplateOutlet="displayField;context:{field:'publisher'}">
+                    </ng-container>
+                  </div>
                 </ng-container>
                 <ng-template #pubDate>
-                  <div class="pb-1" i18n>Pub Date: {{summary.display.pubdate}}</div>
+                  <div class="pb-1" i18n>Pub Date: 
+                    <ng-container 
+                      *ngTemplateOutlet="displayField;context:{field:'pubdate'}">
+                    </ng-container>
+                  </div>
                 </ng-template>
               </ng-container>
               <ng-container *ngIf="summary.display.isbn">
                 <div class="pb-1" i18n>ISBN: 
-                  {{[].concat(summary.display.isbn).join(', ')}}</div>
+                  <ng-container 
+                    *ngTemplateOutlet="displayField;context:{field:'isbn',join:true}">
+                  </ng-container>
+                </div>
               </ng-container>
               <ng-container *ngIf="summary.display.upc">
                 <div class="pb-1" i18n>UPC: 
-                  {{[].concat(summary.display.upc).join(', ')}}</div>
+                  <ng-container 
+                    *ngTemplateOutlet="displayField;context:{field:'upc',join:true}">
+                  </ng-container>
+                </div>
               </ng-container>
               <ng-container *ngIf="summary.display.issn">
                 <div i18n>ISSN: 
-                  {{[].concat(summary.display.issn).join(', ')}}</div>
+                  <ng-container 
+                    *ngTemplateOutlet="displayField;context:{field:'issn',join:true}">
+                  </ng-container>
+                </div>
               </ng-container>
             </div>
           </div>
index 69f4dd0..b79363c 100644 (file)
@@ -121,6 +121,24 @@ export class ResultRecordComponent implements OnInit, OnDestroy {
             return this.basket.removeRecordIds([this.summary.id]);
         }
     }
+
+    // Returns an array of <span>-wrapped display values.
+    // Items are span-wrapped for display consistency between raw
+    // values and search highlight values.
+    getDisplayValues(field: string): string[] {
+        const highlights = this.summary.displayHighlights[field];
+        if (highlights) {
+            if (Array.isArray(highlights)) {
+                return highlights;
+            } else {
+                return [highlights];
+            }
+        } else {
+            let value = this.summary.display[field];
+            if (!Array.isArray(value)) { value = [value]; }
+            return value.map(v => `<span>${v}</span>`);
+        }
+    }
 }