LP1819498 Angular staff catalog call number browse
authorBill Erickson <berickxx@gmail.com>
Mon, 11 Mar 2019 15:37:30 +0000 (11:37 -0400)
committerDan Wells <dbw2@calvin.edu>
Wed, 29 May 2019 19:30:51 +0000 (15:30 -0400)
Implements call number browse as a vertical paged set, similiar to the
browse UI and search results.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Dan Wells <dbw2@calvin.edu>

20 files changed:
Open-ILS/src/eg2/src/app/share/accesskey/accesskey.service.ts
Open-ILS/src/eg2/src/app/share/catalog/catalog-url.service.ts
Open-ILS/src/eg2/src/app/share/catalog/catalog.service.ts
Open-ILS/src/eg2/src/app/share/catalog/search-context.ts
Open-ILS/src/eg2/src/app/staff/catalog/browse.component.html
Open-ILS/src/eg2/src/app/staff/catalog/browse.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/browse/results.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/catalog.component.ts
Open-ILS/src/eg2/src/app/staff/catalog/catalog.module.ts
Open-ILS/src/eg2/src/app/staff/catalog/catalog.service.ts
Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse/results.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse/results.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/catalog/resolver.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
Open-ILS/src/eg2/src/app/staff/catalog/routing.module.ts
Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.html
Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.ts

index 51dda57..0b6302f 100644 (file)
@@ -25,7 +25,9 @@ export class AccessKeyService {
      * string.  For example:  Control and 't' becomes 'ctrl+t'.
      */
     compressKeys(evt: KeyboardEvent): string {
-
+        if (!evt.key) {
+            return null;
+        }
         let s = '';
         if (evt.ctrlKey || evt.metaKey) { s += 'ctrl+'; }
         if (evt.altKey) { s += 'alt+'; }
index 8f326ad..a59b7fc 100644 (file)
@@ -122,6 +122,11 @@ export class CatalogUrlService {
             }
         }
 
+        if (context.cnBrowseSearch.isSearchable()) {
+            params.cnBrowseTerm = context.cnBrowseSearch.value;
+            params.cnBrowsePage = context.cnBrowseSearch.offset;
+        }
+
         return params;
     }
 
@@ -185,6 +190,11 @@ export class CatalogUrlService {
             }
         }
 
+        if (params.get('cnBrowseTerm')) {
+            context.cnBrowseSearch.value = params.get('cnBrowseTerm');
+            context.cnBrowseSearch.offset = Number(params.get('cnBrowsePage'));
+        }
+
         const ts = context.termSearch;
 
         // browseEntry and query searches may be facet-limited
index 90a9599..55fd18e 100644 (file)
@@ -362,4 +362,15 @@ export class CatalogService {
             ctx.searchState = CatalogSearchState.COMPLETE;
         }));
     }
+
+    cnBrowse(ctx: CatalogSearchContext): Observable<any> {
+        ctx.searchState = CatalogSearchState.SEARCHING;
+        const cbs = ctx.cnBrowseSearch;
+
+        return this.net.request(
+            'open-ils.supercat',
+            'open-ils.supercat.call_number.browse',
+            cbs.value, ctx.searchOrg.shortname(), ctx.pager.limit, cbs.offset
+        ).pipe(tap(result => ctx.searchState = CatalogSearchState.COMPLETE));
+    }
 }
index f18a8cd..222536f 100644 (file)
@@ -112,6 +112,22 @@ export class CatalogIdentContext {
 
 }
 
+export class CatalogCnBrowseContext {
+    value: string;
+    // offset in pages from base browse term
+    // e.g. -2 means 2 pages back (alphabetically) from the original search.
+    offset: number;
+
+    reset() {
+        this.value = '';
+        this.offset = 0;
+    }
+
+    isSearchable() {
+        return this.value !== '';
+    }
+}
+
 export class CatalogTermContext {
     fieldClass: string[];
     query: string[];
@@ -214,6 +230,7 @@ export class CatalogSearchContext {
     marcSearch: CatalogMarcContext;
     identSearch: CatalogIdentContext;
     browseSearch: CatalogBrowseContext;
+    cnBrowseSearch: CatalogCnBrowseContext;
 
     // Result from most recent search.
     result: CatalogSearchResults;
@@ -232,6 +249,7 @@ export class CatalogSearchContext {
         this.marcSearch = new CatalogMarcContext();
         this.identSearch = new CatalogIdentContext();
         this.browseSearch = new CatalogBrowseContext();
+        this.cnBrowseSearch = new CatalogCnBrowseContext();
         this.reset();
     }
 
index b50a415..175104b 100644 (file)
@@ -1,5 +1,5 @@
 
 <eg-catalog-search-form #searchForm></eg-catalog-search-form>
 
-<eg-catalog-browse-results><eg-catalog-browse-results>
+<eg-catalog-browse-results></eg-catalog-browse-results>
 
index 67e5eed..bf46a4e 100644 (file)
@@ -1,6 +1,5 @@
 import {Component, OnInit, ViewChild} from '@angular/core';
 import {StaffCatalogService} from './catalog.service';
-import {BasketService} from '@eg/share/catalog/basket.service';
 import {SearchFormComponent} from './search-form.component';
 
 @Component({
@@ -11,17 +10,12 @@ export class BrowseComponent implements OnInit {
     @ViewChild('searchForm') searchForm: SearchFormComponent;
 
     constructor(
-        private staffCat: StaffCatalogService,
-        private basket: BasketService
+        private staffCat: StaffCatalogService
     ) {}
 
     ngOnInit() {
         // A SearchContext provides all the data needed for browse.
         this.staffCat.createContext();
-
-        // Cache the basket on page load.
-        this.basket.getRecordIds();
-
         this.searchForm.searchTab = 'browse';
     }
 }
index 65d02e5..e8b3499 100644 (file)
@@ -1,38 +1,37 @@
-import {Component, OnInit, Input} from '@angular/core';
-import {Observable, Subscription} from 'rxjs';
-import {map, switchMap, distinctUntilChanged} from 'rxjs/operators';
+import {Component, OnInit, OnDestroy} from '@angular/core';
 import {ActivatedRoute, ParamMap} from '@angular/router';
+import {Subscription} from 'rxjs';
 import {CatalogService} from '@eg/share/catalog/catalog.service';
-import {BibRecordService} from '@eg/share/catalog/bib-record.service';
 import {CatalogUrlService} from '@eg/share/catalog/catalog-url.service';
 import {CatalogSearchContext, CatalogSearchState} from '@eg/share/catalog/search-context';
-import {PcrudService} from '@eg/core/pcrud.service';
 import {StaffCatalogService} from '../catalog.service';
-import {IdlObject} from '@eg/core/idl.service';
 
 @Component({
   selector: 'eg-catalog-browse-results',
   templateUrl: 'results.component.html'
 })
-export class BrowseResultsComponent implements OnInit {
+export class BrowseResultsComponent implements OnInit, OnDestroy {
 
     searchContext: CatalogSearchContext;
     results: any[];
+    routeSub: Subscription;
 
     constructor(
         private route: ActivatedRoute,
-        private pcrud: PcrudService,
         private cat: CatalogService,
-        private bib: BibRecordService,
         private catUrl: CatalogUrlService,
         private staffCat: StaffCatalogService
     ) {}
 
     ngOnInit() {
         this.searchContext = this.staffCat.searchContext;
-        this.route.queryParamMap.subscribe((params: ParamMap) => {
-            this.browseByUrl(params);
-        });
+        this.routeSub = this.route.queryParamMap.subscribe(
+            (params: ParamMap) => this.browseByUrl(params)
+        );
+    }
+
+    ngOnDestroy() {
+        this.routeSub.unsubscribe();
     }
 
     browseByUrl(params: ParamMap): void {
index 0e2fc98..f9fcf6d 100644 (file)
@@ -17,9 +17,6 @@ export class CatalogComponent implements OnInit {
         // child components.  After initial creation, the context is
         // reset and updated as needed to apply new search parameters.
         this.staffCat.createContext();
-
-        // Cache the basket on page load.
-        this.basket.getRecordIds();
     }
 }
 
index b07938a..e78a951 100644 (file)
@@ -24,6 +24,8 @@ import {BrowseComponent} from './browse.component';
 import {BrowseResultsComponent} from './browse/results.component';
 import {HoldingsMaintenanceComponent} from './record/holdings.component';
 import {ConjoinedComponent} from './record/conjoined.component';
+import {CnBrowseComponent} from './cnbrowse.component';
+import {CnBrowseResultsComponent} from './cnbrowse/results.component';
 
 @NgModule({
   declarations: [
@@ -44,7 +46,9 @@ import {ConjoinedComponent} from './record/conjoined.component';
     BrowseComponent,
     BrowseResultsComponent,
     ConjoinedComponent,
-    HoldingsMaintenanceComponent
+    HoldingsMaintenanceComponent,
+    CnBrowseComponent,
+    CnBrowseResultsComponent
   ],
   imports: [
     StaffCommonModule,
index cf0a36c..3b4f696 100644 (file)
@@ -89,7 +89,6 @@ export class StaffCatalogService {
      */
     browse(): void {
         if (!this.searchContext.browseSearch.isSearchable()) { return; }
-
         const params = this.catUrl.toUrlParams(this.searchContext);
 
         // Force a new browse every time this method is called, even if
@@ -102,7 +101,16 @@ export class StaffCatalogService {
         params.ridx = '' + this.routeIndex++;
 
         this.router.navigate(
-          ['/staff/catalog/browse'], {queryParams: params});
+            ['/staff/catalog/browse'], {queryParams: params});
+    }
+
+    // Call number browse.
+    // Redirect to cn browse page and let its component perform the search
+    cnBrowse(): void {
+        if (!this.searchContext.cnBrowseSearch.isSearchable()) { return; }
+        const params = this.catUrl.toUrlParams(this.searchContext);
+        params.ridx = '' + this.routeIndex++; // see comments above
+        this.router.navigate(['/staff/catalog/cnbrowse'], {queryParams: params});
     }
 }
 
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse.component.html
new file mode 100644 (file)
index 0000000..9be00ff
--- /dev/null
@@ -0,0 +1,5 @@
+
+<eg-catalog-search-form #searchForm></eg-catalog-search-form>
+
+<eg-catalog-cn-browse-results></eg-catalog-cn-browse-results>
+
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse.component.ts
new file mode 100644 (file)
index 0000000..e0f7bf7
--- /dev/null
@@ -0,0 +1,22 @@
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {StaffCatalogService} from './catalog.service';
+import {SearchFormComponent} from './search-form.component';
+
+@Component({
+  templateUrl: 'cnbrowse.component.html'
+})
+export class CnBrowseComponent implements OnInit {
+
+    @ViewChild('searchForm') searchForm: SearchFormComponent;
+
+    constructor(
+        private staffCat: StaffCatalogService,
+    ) {}
+
+    ngOnInit() {
+        // A SearchContext provides all the data needed for browse.
+        this.staffCat.createContext();
+        this.searchForm.searchTab = 'cnbrowse';
+    }
+}
+
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse/results.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse/results.component.html
new file mode 100644 (file)
index 0000000..09a1f4e
--- /dev/null
@@ -0,0 +1,52 @@
+<!-- search results progress bar -->
+<div class="row" *ngIf="browseIsActive()">
+  <div class="col-lg-6 offset-lg-3 pt-3">
+    <div class="progress">
+      <div class="progress-bar progress-bar-striped active w-100"
+        role="progressbar" aria-valuenow="100" 
+        aria-valuemin="0" aria-valuemax="100">
+        <span class="sr-only" i18n>Searching..</span>
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- no items found -->
+<div *ngIf="browseIsDone() && !browseHasResults()">
+  <div class="row pt-3">
+    <div class="col-lg-6 offset-lg-3">
+      <div class="alert alert-warning">
+        <span i18n>No Maching Items Were Found</span>
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- header, pager, and list of records -->
+<div id="staff-catalog-browse-results-container" *ngIf="browseHasResults()">
+
+  <div class="row mb-2">
+    <div class="col-lg-3">
+      <button class="btn btn-primary" (click)="prevPage()">Back</button>
+      <button class="btn btn-primary ml-3" (click)="nextPage()">Next</button>
+    </div>
+  </div>
+
+  <div class="row" *ngFor="let result of results; let idx = index">
+    <div class="col-lg-12" *ngIf="result._bibSummary">
+      <eg-catalog-result-record [summary]="result._bibSummary" 
+        [index]="idx" [callNumber]="result">
+      </eg-catalog-result-record>
+    </div>
+  </div>
+
+  <div class="row mb-2">
+    <div class="col-lg-3">
+      <button class="btn btn-primary" (click)="prevPage()">Back</button>
+      <button class="btn btn-primary ml-3" (click)="nextPage()">Next</button>
+    </div>
+  </div>
+
+</div>
+
+
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse/results.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse/results.component.ts
new file mode 100644 (file)
index 0000000..037b9ea
--- /dev/null
@@ -0,0 +1,122 @@
+import {Component, OnInit, OnDestroy} from '@angular/core';
+import {ActivatedRoute, Router, ParamMap} from '@angular/router';
+import {Subscription} from 'rxjs';
+import {IdlObject} from '@eg/core/idl.service';
+import {CatalogService} from '@eg/share/catalog/catalog.service';
+import {BibRecordService} from '@eg/share/catalog/bib-record.service';
+import {CatalogUrlService} from '@eg/share/catalog/catalog-url.service';
+import {CatalogSearchContext, CatalogSearchState} from '@eg/share/catalog/search-context';
+import {StaffCatalogService} from '../catalog.service';
+import {BibRecordSummary} from '@eg/share/catalog/bib-record.service';
+
+@Component({
+  selector: 'eg-catalog-cn-browse-results',
+  templateUrl: 'results.component.html'
+})
+export class CnBrowseResultsComponent implements OnInit, OnDestroy {
+
+    searchContext: CatalogSearchContext;
+    results: any[];
+    routeSub: Subscription;
+
+    constructor(
+        private router: Router,
+        private route: ActivatedRoute,
+        private cat: CatalogService,
+        private bib: BibRecordService,
+        private catUrl: CatalogUrlService,
+        private staffCat: StaffCatalogService
+    ) {}
+
+    ngOnInit() {
+        this.searchContext = this.staffCat.searchContext;
+        this.routeSub = this.route.queryParamMap.subscribe(
+            (params: ParamMap) => this.browseByUrl(params)
+        );
+    }
+
+    ngOnDestroy() {
+        this.routeSub.unsubscribe();
+    }
+
+    browseByUrl(params: ParamMap): void {
+        this.catUrl.applyUrlParams(this.searchContext, params);
+        const cbs = this.searchContext.cnBrowseSearch;
+
+        if (cbs.isSearchable()) {
+            this.results = [];
+            this.cat.cnBrowse(this.searchContext)
+                .subscribe(results => this.processResults(results));
+        }
+    }
+
+    processResults(results: any[]) {
+        this.results = results;
+
+        const depth = this.searchContext.global ?
+            this.searchContext.org.root().ou_type().depth() :
+            this.searchContext.searchOrg.ou_type().depth();
+
+        const bibIds = this.results.map(r => r.record().id());
+        const distinct = (value: any, index: number, self: Array<number>) => {
+            return self.indexOf(value) === index;
+        };
+
+        const bres: IdlObject[] = [];
+        this.bib.getBibSummary(
+            bibIds.filter(distinct),
+            this.searchContext.searchOrg.id(), depth
+        ).subscribe(
+            summary => {
+                // Response order not guaranteed.  Match the summary
+                // object up with its response object.  A bib may be
+                // linked to multiple call numbers
+                const bibResults = this.results.filter(
+                    r => Number(r.record().id()) === summary.id);
+
+                bres.push(summary.record);
+
+                // Use _ since result is an 'acn' object.
+                bibResults.forEach(r => r._bibSummary = summary);
+            },
+            err => {},
+            ()  => {
+                this.bib.fleshBibUsers(bres);
+            }
+        );
+    }
+
+    browseIsDone(): boolean {
+        return this.searchContext.searchState === CatalogSearchState.COMPLETE;
+    }
+
+    browseIsActive(): boolean {
+        return this.searchContext.searchState === CatalogSearchState.SEARCHING;
+    }
+
+    browseHasResults(): boolean {
+        return this.browseIsDone() && this.results.length > 0;
+    }
+
+    prevPage() {
+        this.searchContext.cnBrowseSearch.offset--;
+        this.staffCat.cnBrowse();
+    }
+
+    nextPage() {
+        this.searchContext.cnBrowseSearch.offset++;
+        this.staffCat.cnBrowse();
+    }
+
+    /**
+     * Propagate the search params along when navigating to each record.
+     */
+    navigateToRecord(summary: BibRecordSummary) {
+        const params = this.catUrl.toUrlParams(this.searchContext);
+
+        this.router.navigate(
+            ['/staff/catalog/record/' + summary.id], {queryParams: params});
+    }
+}
+
+
index 0a09cbd..1dac536 100644 (file)
@@ -1,14 +1,14 @@
 import {Injectable} from '@angular/core';
-import {Observable, Observer} from 'rxjs';
 import {Router, Resolve, RouterStateSnapshot,
         ActivatedRouteSnapshot} from '@angular/router';
 import {ServerStoreService} from '@eg/core/server-store.service';
 import {NetService} from '@eg/core/net.service';
 import {OrgService} from '@eg/core/org.service';
 import {AuthService} from '@eg/core/auth.service';
-import {PcrudService} from '@eg/core/pcrud.service';
 import {CatalogService} from '@eg/share/catalog/catalog.service';
 import {StaffCatalogService} from './catalog.service';
+import {BasketService} from '@eg/share/catalog/basket.service';
+
 
 @Injectable()
 export class CatalogResolver implements Resolve<Promise<any[]>> {
@@ -20,7 +20,8 @@ export class CatalogResolver implements Resolve<Promise<any[]>> {
         private net: NetService,
         private auth: AuthService,
         private cat: CatalogService,
-        private staffCat: StaffCatalogService
+        private staffCat: StaffCatalogService,
+        private basket: BasketService
     ) {}
 
     resolve(
@@ -32,7 +33,8 @@ export class CatalogResolver implements Resolve<Promise<any[]>> {
         return Promise.all([
             this.cat.fetchCcvms(),
             this.cat.fetchCmfs(),
-            this.fetchSettings()
+            this.fetchSettings(),
+            this.basket.getRecordIds()
         ]);
     }
 
index 9a65daf..eb33fe8 100644 (file)
             <img src="/opac/extras/ac/jacket/small/r/{{summary.id}}"/>
           </a>
         </div>
+        <!-- for call number browse display -->
+        <ng-container *ngIf="callNumber">
+          <div class="pl-2 font-weight-bold">
+            {{callNumber.prefix().label()}}
+            {{callNumber.label()}}
+            {{callNumber.suffix().label()}}
+            @ {{orgName(callNumber.owning_lib())}}
+          </div>
+        </ng-container>
         <div class="flex-1 pl-2">
           <div class="row">
             <div class="col-lg-12 font-weight-bold">
index dd13b9d..8505e76 100644 (file)
@@ -3,6 +3,7 @@ import {Subscription} from 'rxjs';
 import {Router} from '@angular/router';
 import {OrgService} from '@eg/core/org.service';
 import {NetService} from '@eg/core/net.service';
+import {IdlObject} from '@eg/core/idl.service';
 import {CatalogService} from '@eg/share/catalog/catalog.service';
 import {BibRecordService, BibRecordSummary} from '@eg/share/catalog/bib-record.service';
 import {CatalogSearchContext} from '@eg/share/catalog/search-context';
@@ -19,6 +20,12 @@ export class ResultRecordComponent implements OnInit, OnDestroy {
 
     @Input() index: number;  // 0-index display row
     @Input() summary: BibRecordSummary;
+
+    // Optional call number (acn) object to highlight
+    // Assumed prefix/suffix are fleshed
+    // Used by call number browse.
+    @Input() callNumber: IdlObject;
+
     searchContext: CatalogSearchContext;
     isRecordSelected: boolean;
     basketSub: Subscription;
index 8bcef4f..e0da65f 100644 (file)
@@ -6,6 +6,7 @@ import {RecordComponent} from './record/record.component';
 import {CatalogResolver} from './resolver.service';
 import {HoldComponent} from './hold/hold.component';
 import {BrowseComponent} from './browse.component';
+import {CnBrowseComponent} from './cnbrowse.component';
 
 const routes: Routes = [{
   path: '',
@@ -24,11 +25,16 @@ const routes: Routes = [{
     path: 'record/:id/:tab',
     component: RecordComponent
   }]}, {
-  // Browse is a top-level UI
-  path: 'browse',
-  component: BrowseComponent,
-  resolve: {catResolver : CatalogResolver},
-}];
+    // Browse is a top-level UI
+    path: 'browse',
+    component: BrowseComponent,
+    resolve: {catResolver : CatalogResolver}
+  }, {
+    path: 'cnbrowse',
+    component: CnBrowseComponent,
+    resolve: {catResolver : CatalogResolver}
+  }
+];
 
 @NgModule({
   imports: [RouterModule.forChild(routes)],
index ee4abc5..18af372 100644 (file)
@@ -296,6 +296,22 @@ TODO focus search input
           </div>
         </ng-template>
       </ngb-tab>
+      <ngb-tab title="Shelf Browse" i18n-title id="cnbrowse">
+        <ng-template ngbTabContent>
+          <div class="row mt-4">
+            <div class="col-lg-12 form-inline">
+              <label for="cnbrowse-term-input" i18n>
+                Browse Call Numbers starting with 
+              </label>
+              <input type="text" class="form-control ml-2" 
+                id='cnbrowse-term-input' name="query"
+                [(ngModel)]="context.cnBrowseSearch.value"
+                (keyup.enter)="searchByForm()"
+                placeholder="Browse Call Numbers..."/>
+            </div>
+          </div>
+        </ng-template>
+      </ngb-tab>      
     </ngb-tabset>
   </div>
   <div class="col-lg-4">
index 785e69e..c8cee02 100644 (file)
@@ -81,7 +81,7 @@ export class SearchFormComponent implements OnInit, AfterViewInit {
 
     focusTabInput() {
         // Select a DOM node to focus when the tab changes.
-        let selector;
+        let selector: string;
         switch (this.searchTab) {
             case 'ident':
                 selector = '#ident-query-input';
@@ -92,6 +92,9 @@ export class SearchFormComponent implements OnInit, AfterViewInit {
             case 'browse':
                 selector = '#browse-term-input';
                 break;
+            case 'cnbrowse':
+                selector = '#cnbrowse-term-input';
+                break;
             default:
                 this.refreshCopyLocations();
                 selector = '#first-query-input';
@@ -197,6 +200,7 @@ export class SearchFormComponent implements OnInit, AfterViewInit {
                 this.context.marcSearch.reset();
                 this.context.browseSearch.reset();
                 this.context.identSearch.reset();
+                this.context.cnBrowseSearch.reset();
                 this.context.termSearch.hasBrowseEntry = '';
                 this.context.termSearch.browseEntry = null;
                 this.context.termSearch.fromMetarecord = null;
@@ -208,6 +212,7 @@ export class SearchFormComponent implements OnInit, AfterViewInit {
                 this.context.marcSearch.reset();
                 this.context.browseSearch.reset();
                 this.context.termSearch.reset();
+                this.context.cnBrowseSearch.reset();
                 this.staffCat.search();
                 break;
 
@@ -215,6 +220,7 @@ export class SearchFormComponent implements OnInit, AfterViewInit {
                 this.context.browseSearch.reset();
                 this.context.termSearch.reset();
                 this.context.identSearch.reset();
+                this.context.cnBrowseSearch.reset();
                 this.staffCat.search();
                 break;
 
@@ -222,9 +228,19 @@ export class SearchFormComponent implements OnInit, AfterViewInit {
                 this.context.marcSearch.reset();
                 this.context.termSearch.reset();
                 this.context.identSearch.reset();
+                this.context.cnBrowseSearch.reset();
                 this.context.browseSearch.pivot = null;
                 this.staffCat.browse();
                 break;
+
+            case 'cnbrowse':
+                this.context.marcSearch.reset();
+                this.context.termSearch.reset();
+                this.context.identSearch.reset();
+                this.context.browseSearch.reset();
+                this.context.cnBrowseSearch.offset = 0;
+                this.staffCat.cnBrowse();
+                break;
         }
     }
 
@@ -236,10 +252,6 @@ export class SearchFormComponent implements OnInit, AfterViewInit {
     searchIsActive(): boolean {
         return this.context.searchState === CatalogSearchState.SEARCHING;
     }
-
-    goToBrowse() {
-        this.router.navigate(['/staff/catalog/browse']);
-    }
 }