LP#626157 Ang2 experiments
authorBill Erickson <berickxx@gmail.com>
Thu, 7 Dec 2017 03:13:19 +0000 (22:13 -0500)
committerBill Erickson <berickxx@gmail.com>
Mon, 11 Dec 2017 17:39:51 +0000 (12:39 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/webby-src/src/app/share/catalog/catalog.service.ts
Open-ILS/webby-src/src/app/share/catalog/search-context.ts
Open-ILS/webby-src/src/app/staff/catalog/resolver.service.ts
Open-ILS/webby-src/src/app/staff/catalog/result/facets.component.html
Open-ILS/webby-src/src/app/staff/catalog/result/facets.component.ts
Open-ILS/webby-src/src/app/staff/catalog/result/record.component.html
Open-ILS/webby-src/src/app/staff/catalog/result/results.component.html
Open-ILS/webby-src/src/app/staff/catalog/result/results.component.ts
Open-ILS/webby-src/src/app/staff/catalog/search-form.component.html
Open-ILS/webby-src/src/app/staff/catalog/search-form.component.ts

index f7efc0f..e88d12f 100644 (file)
@@ -22,7 +22,7 @@ export const CATALOG_CCVM_FILTERS = [
 export class EgCatalogService {
 
     ccvmMap: {[ccvm:string] : EgIdlObject[]} = {};
-    cmfMap: {[cmf:string] : EgIdlObject[]} = {};
+    cmfMap: {[cmf:string] : EgIdlObject} = {};
 
     constructor(
         private net: EgNetService,
@@ -32,7 +32,6 @@ export class EgCatalogService {
     ) {}
 
     search(ctx: CatalogSearchContext): Promise<void> {
-        ctx.result = {};
         ctx.searchInProgress = true;
 
         var fullQuery = ctx.compileSearch();
@@ -74,6 +73,46 @@ export class EgCatalogService {
         })
     }
 
+    fetchFacets(ctx: CatalogSearchContext): Promise<void> {
+
+        if (!ctx.result) return Promise.resolve();
+
+        return new Promise((resolve, reject) => {
+            this.net.request('open-ils.search', 
+                'open-ils.search.facet_cache.retrieve',
+                ctx.result.facet_key
+            ).subscribe(facets => {
+                let facetData = {};
+                Object.keys(facets).forEach(cmfId => {
+                    let facetHash = facets[cmfId];
+                    let cmf = this.cmfMap[cmfId];
+
+                    let cmfData = [];
+                    Object.keys(facetHash).forEach(value => {
+                        let count = facetHash[value];
+                        cmfData.push({value : value, count : count});
+                    });
+
+                    if (!facetData[cmf.field_class()])
+                        facetData[cmf.field_class()] = {};
+
+                    facetData[cmf.field_class()][cmf.name()] = {
+                        cmfLabel : cmf.label(),
+                        valueList : cmfData.sort((a, b) => {
+                            if (a.count > b.count) return -1;
+                            if (a.count < b.count) return 1;
+                            // secondary alpha sort on display value
+                            return a.value < b.value ? -1 : 1;
+                        })
+                    };
+                });
+
+                ctx.result.facetData = facetData;
+                resolve();
+            });
+        })
+    }
+
     fetchCcvms(): Promise<void> {
 
         if (Object.keys(this.ccvmMap).length) 
index a77cb6c..d71b063 100644 (file)
@@ -30,7 +30,7 @@ export class CatalogSearchContext {
     isStaff: boolean;
 
     // Result from most recent search.
-    result: any
+    result: any = {};
     searchInProgress: boolean = false;
 
     // Utility stuff
index e948cbb..8929d55 100644 (file)
@@ -28,7 +28,8 @@ export class EgCatalogResolver implements Resolve<Promise<any[]>> {
         console.debug('EgCatalogResolver:resolve()');
 
         return Promise.all([
-            this.cat.fetchCcvms()
+            this.cat.fetchCcvms(),
+            this.cat.fetchCmfs()
         ]);
     }
 }
index 124d5e7..a951dc9 100644 (file)
@@ -1 +1,42 @@
-TEST FACETS
+<style>
+  .facet-selected {
+    background-color: #DDD;
+  }
+  .card {
+    width: 100%;
+  }
+  .list-group-item {padding: .5rem .75rem .5rem .75rem}
+</style>
+<div *ngIf="searchContext.result.facetData">
+  <div *ngFor="let facetConf of facetConfig.display">
+    <div *ngIf="searchContext.result.facetData[facetConf.facetClass]">
+      <div *ngFor="let name of facetConf.facetOrder">
+        <div class="row"
+          *ngIf="searchContext.result.facetData[facetConf.facetClass][name]">
+          <div class="card mb-2">
+            <h5 class="card-header">
+              {{searchContext.result.facetData[facetConf.facetClass][name].cmfLabel}}
+            </h5>
+            <ul class="list-group list-group-flush">
+              <li class="list-group-item" 
+                [ngClass]="{'facet-selected' :
+                  facetIsApplied(facetConf.facetClass, name, value.value)}"
+                *ngFor="
+                  let value of searchContext.result.facetData[facetConf.facetClass][name].valueList | slice:0:facetConfig.displayCount">
+                <div class="row">
+                  <div class="col-10">
+                    <a class="card-link"
+                      (click)="context.apply_facet(facetConf.facetClass, name, value.value)">
+                      {{value.value}}
+                    </a>
+                  </div>
+                  <div class="col-2">{{value.count}}</div>
+                </div>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
index 03d8a2f..6bfce97 100644 (file)
@@ -3,6 +3,17 @@ import {EgCatalogService} from '@eg/share/catalog/catalog.service';
 import {CatalogSearchContext} from '@eg/share/catalog/search-context';
 import {StaffCatalogService} from '../staff-catalog.service';
 
+export const FACET_CONFIG = {
+               display: [
+                               {facetClass : 'author',  facetOrder : ['personal', 'corporate']},
+                               {facetClass : 'subject', facetOrder : ['topic']},
+                               {facetClass : 'identifier', facetOrder : ['genre']},
+                               {facetClass : 'series',  facetOrder : ['seriestitle']},
+                               {facetClass : 'subject', facetOrder : ['name', 'geographic']}
+               ],
+               displayCount : 5
+};
+
 @Component({
   selector: 'eg-catalog-result-facets',
   styleUrls: ['facets.component.css'],
@@ -11,16 +22,28 @@ import {StaffCatalogService} from '../staff-catalog.service';
 export class ResultFacetsComponent implements OnInit {
 
     searchContext: CatalogSearchContext;
+    facetConfig: any;
 
     constructor(
         private cat: EgCatalogService,
         private staffCat: StaffCatalogService
-    ) {}
+    ) {
+        this.facetConfig = FACET_CONFIG;
+               }
 
     ngOnInit() { 
         this.searchContext = this.staffCat.searchContext;
     }
 
+    facetIsApplied(cls: string, name: string, value: string) {
+        return this.searchContext.facetFilters.filter(f => {
+            return (
+                f.facetClass == cls &&
+                f.facetName == name &&
+                f.facetValue == value
+            );
+        })[0];
+    }
 }
 
 
index e04da00..7c817ce 100644 (file)
           <div class="float-right">
             <span>
               <button (click)="placeHold()"
-                class="btn btn-sm btn-success with-material-icon weak-text-1">
+                class="btn btn-sm btn-outline-success with-material-icon weak-text-1">
                 <span class="material-icons">check</span>
                 <span i18n>Place Hold</span>
               </button>
             </span>
             <span>
               <button (click)="addToList()" 
-                class="btn btn-sm btn-info with-material-icon weak-text-1">
+                class="btn btn-sm btn-outline-info with-material-icon weak-text-1">
                 <span class="material-icons">playlist_add_check</span>
                 <span i18n>Add to List</span>
               </button>
index cf88c4c..796016c 100644 (file)
@@ -13,7 +13,7 @@
   </div>
        <div class="row">
                <div class="col-2">
-                       <!-- facets -->
+      <eg-catalog-result-facets></eg-catalog-result-facets>
                </div>
                <div class="col-10">
                        <div *ngIf="searchContext.result">
index 1e0b098..290d358 100644 (file)
@@ -57,6 +57,7 @@ export class ResultsComponent implements OnInit {
         if (!this.searchContext.query[0]) return;
 
         this.cat.search(this.searchContext).then(ok => {
+            this.cat.fetchFacets(this.searchContext);
             this.fleshSearchResults();
         });
     }
index 1d6949b..831bb3d 100644 (file)
@@ -73,12 +73,12 @@ TODO focus search input
           (click)="searchContext.reset()">
           Clear Form
         </button>
-        <button class="btn btn-secondary" type="button"
+        <button class="btn btn-outline-secondary" type="button"
           *ngIf="!showAdvanced()"
           (click)="showAdvancedSearch=true">
           More Filters...
         </button>
-        <button class="btn btn-secondary" type="button"
+        <button class="btn btn-outline-secondary" type="button"
           *ngIf="showAdvanced()"
           (click)="showAdvancedSearch=false">
           Hide Filters
index 08ff529..db2dbaf 100644 (file)
@@ -14,7 +14,7 @@ export class SearchFormComponent implements OnInit {
 
     searchContext: CatalogSearchContext;
     ccvmMap: {[ccvm:string] : EgIdlObject[]} = {};
-    cmfMap: {[cmf:string] : EgIdlObject[]} = {};
+    cmfMap: {[cmf:string] : EgIdlObject} = {};
     showAdvancedSearch: boolean = false;
 
     constructor(