<!--
TODO focus search input
-->
-<div id='staffcat-search-form' class='pb-2 mb-4'>
- <div class="row"
- *ngFor="let q of searchContext.query; let idx = index; trackBy:trackByIdx">
- <div class="col-lg-8 d-flex">
- <div class="flex-1">
- <div *ngIf="idx == 0">
- <select class="form-control" [(ngModel)]="searchContext.format">
- <option i18n value=''>All Formats</option>
- <option *ngFor="let fmt of ccvmMap.search_format"
- value="{{fmt.code()}}">{{fmt.value()}}</option>
- </select>
- </div>
- <div *ngIf="idx > 0">
- <select class="form-control"
- [(ngModel)]="searchContext.joinOp[idx]">
- <option i18n value='&&'>And</option>
- <option i18n value='||'>Or</option>
- </select>
- </div>
- </div>
- <div class="flex-1 pl-1">
- <select class="form-control"
- [(ngModel)]="searchContext.fieldClass[idx]">
- <option i18n value='keyword'>Keyword</option>
- <option i18n value='title'>Title</option>
- <option i18n value='jtitle'>Journal Title</option>
- <option i18n value='author'>Author</option>
- <option i18n value='subject'>Subject</option>
- <option i18n value='series'>Series</option>
- </select>
- </div>
- <div class="flex-1 pl-1">
- <select class="form-control"
- [(ngModel)]="searchContext.matchOp[idx]">
- <option i18n value='contains'>Contains</option>
- <option i18n value='nocontains'>Does not contain</option>
- <option i18n value='phrase'>Contains phrase</option>
- <option i18n value='exact'>Matches exactly</option>
- <option i18n value='starts'>Starts with</option>
- </select>
- </div>
- <div class="flex-2 pl-1">
- <div class="form-group">
- <div *ngIf="idx == 0">
- <input type="text" class="form-control"
- id='first-query-input'
- [(ngModel)]="searchContext.query[idx]"
- (keyup.enter)="formEnter('query')"
- placeholder="Query..."/>
- </div>
- <div *ngIf="idx > 0">
- <input type="text" class="form-control"
- [(ngModel)]="searchContext.query[idx]"
- (keyup.enter)="formEnter('query')"
- placeholder="Query..."/>
- </div>
- </div>
- </div>
- <div class="flex-1 pl-1">
- <button class="btn btn-sm material-icon-button"
- (click)="addSearchRow(idx + 1)">
- <span class="material-icons">add_circle_outline</span>
- </button>
- <button class="btn btn-sm material-icon-button"
- [disabled]="searchContext.query.length < 2"
- (click)="delSearchRow(idx)">
- <span class="material-icons">remove_circle_outline</span>
- </button>
- </div>
- </div><!-- col -->
- <div class="col-lg-4">
- <div *ngIf="idx == 0" class="float-right">
- <button class="btn btn-success mr-1" type="button"
- [disabled]="searchIsActive()"
- (click)="searchContext.pager.offset=0;searchByForm()" i18n>
- Search
- </button>
- <button class="btn btn-warning mr-1" type="button"
- [disabled]="searchIsActive()"
- (click)="searchContext.reset()" i18n>
- Clear Form
- </button>
- <button class="btn btn-outline-secondary" type="button"
- *ngIf="!showAdvanced()"
- [disabled]="searchIsActive()"
- (click)="toggleAdvancedSearch()" i18n>
- More Options
- </button>
- <button class="btn btn-outline-secondary" type="button"
- *ngIf="showAdvanced()"
- (click)="toggleAdvancedSearch()" i18n>
- Hide Options
- </button>
- <button class="btn btn-info ml-1" type="button"
- (click)="goToBrowse()" i18n>
- Browse
- </button>
- </div>
- </div>
- </div><!-- row -->
-
- <div class="row">
- <div class="col-lg-8 d-flex">
- <div class="flex-1">
- <eg-org-select
- (onChange)="orgOnChange($event)"
- [initialOrg]="searchContext.searchOrg"
- [placeholder]="'Library'" >
- </eg-org-select>
- </div>
- <div class="flex-3 pl-1">
- <select class="form-control" [(ngModel)]="searchContext.sort">
- <option value='' i18n>Sort by Relevance</option>
- <optgroup label="Sort by Title" i18n-label>
- <option value='titlesort' i18n>Title: A to Z</option>
- <option value='titlesort.descending' i18n>Title: Z to A</option>
- </optgroup>
- <optgroup label="Sort by Author" i18n-label>
- <option value='authorsort' i18n>Author: A to Z</option>
- <option value='authorsort.descending' i18n>Author: Z to A</option>
- </optgroup>
- <optgroup label="Sort by Publication Date" i18n-label>
- <option value='pubdate' i18n>Date: A to Z</option>
- <option value='pubdate.descending' i18n>Date: Z to A</option>
- </optgroup>
- <optgroup label="Sort by Popularity" i18n-label>
- <option value='popularity' i18n>Most Popular</option>
- <option value='poprel' i18n>Popularity Adjusted Relevance</option>
- </optgroup>
- </select>
- </div>
- <div class="flex-2 pl-2 align-self-end">
- <div class="checkbox">
- <label>
- <input type="checkbox" [(ngModel)]="searchContext.available"/>
- <span class="pl-1" i18n>Limit to Available</span>
- </label>
- </div>
- </div>
- <div class="flex-4 pl-2 align-self-end">
- <div class="checkbox">
- <label>
- <input type="checkbox" [(ngModel)]="searchContext.global"/>
- <span class="pl-1" i18n>Show Results from All Libraries</span>
- </label>
- </div>
- </div>
- <div class="flex-2 pl-1">
- <!-- alignment -->
- </div>
- </div>
- <div class="col-lg-4">
- <eg-catalog-basket-actions></eg-catalog-basket-actions>
- </div>
- </div>
-
- <div class="p-2 m-2" *ngIf="showAdvanced()">
+<div id='staffcat-search-form' class="row pb-3 mb-3 ">
+ <div class="col-lg-8">
<ngb-tabset #searchTabs [activeId]="searchTab" (tabChange)="onTabChange($event)">
- <ngb-tab title="Search Filters" i18n-title id="filters">
+ <ngb-tab title="Term Search" i18n-title id="term">
<ng-template ngbTabContent>
- <div class="row mt-3">
- <div class="col-lg-2">
+ <div class="row"
+ [ngClass]="{'mt-4': idx == 0, 'mt-1': idx > 0}"
+ *ngFor="let q of searchContext.query; let idx = index; trackBy:trackByIdx">
+ <div class="col-lg-2 pr-1">
+ <div *ngIf="idx == 0">
+ <select class="form-control" [(ngModel)]="searchContext.format">
+ <option i18n value=''>All Formats</option>
+ <option *ngFor="let fmt of ccvmMap.search_format"
+ value="{{fmt.code()}}">{{fmt.value()}}</option>
+ </select>
+ </div>
+ <div *ngIf="idx > 0">
+ <select class="form-control"
+ [(ngModel)]="searchContext.joinOp[idx]">
+ <option i18n value='&&'>And</option>
+ <option i18n value='||'>Or</option>
+ </select>
+ </div>
+ </div>
+ <div class="col-lg-2 pl-0 pr-2">
+ <select class="form-control"
+ [(ngModel)]="searchContext.fieldClass[idx]">
+ <option i18n value='keyword'>Keyword</option>
+ <option i18n value='title'>Title</option>
+ <option i18n value='jtitle'>Journal Title</option>
+ <option i18n value='author'>Author</option>
+ <option i18n value='subject'>Subject</option>
+ <option i18n value='series'>Series</option>
+ </select>
+ </div>
+ <div class="col-lg-2 pl-0 pr-2">
+ <select class="form-control"
+ [(ngModel)]="searchContext.matchOp[idx]">
+ <option i18n value='contains'>Contains</option>
+ <option i18n value='nocontains'>Does not contain</option>
+ <option i18n value='phrase'>Contains phrase</option>
+ <option i18n value='exact'>Matches exactly</option>
+ <option i18n value='starts'>Starts with</option>
+ </select>
+ </div>
+ <div class="col-lg-4 pl-0 pr-2">
+ <div class="form-group">
+ <div *ngIf="idx == 0">
+ <input type="text" class="form-control"
+ id='first-query-input'
+ [(ngModel)]="searchContext.query[idx]"
+ (keyup.enter)="searchByForm()"
+ placeholder="Query..."/>
+ </div>
+ <div *ngIf="idx > 0">
+ <input type="text" class="form-control"
+ [(ngModel)]="searchContext.query[idx]"
+ (keyup.enter)="searchByForm()"
+ placeholder="Query..."/>
+ </div>
+ </div>
+ </div>
+ <div class="col-lg-2 pl-0 pr-1">
+ <button class="btn btn-sm material-icon-button"
+ (click)="addSearchRow(idx + 1)"
+ i18n-title title="Add Search Row">
+ <span class="material-icons">add_circle_outline</span>
+ </button>
+ <button class="btn btn-sm material-icon-button"
+ [disabled]="searchContext.query.length < 2"
+ (click)="delSearchRow(idx)"
+ i18n-title title="Remove Search Row">
+ <span class="material-icons">remove_circle_outline</span>
+ </button>
+ <button *ngIf="idx == 0"
+ class="btn btn-sm material-icon-button"
+ type="button" (click)="toggleFilters()"
+ title="Toggle Search Filters" i18n-title>
+ <span class="material-icons">more_vert</span>
+ </button>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-12 form-inline">
+ <select class="form-control mr-2" [(ngModel)]="searchContext.sort">
+ <option value='' i18n>Sort by Relevance</option>
+ <optgroup label="Sort by Title" i18n-label>
+ <option value='titlesort' i18n>Title: A to Z</option>
+ <option value='titlesort.descending' i18n>Title: Z to A</option>
+ </optgroup>
+ <optgroup label="Sort by Author" i18n-label>
+ <option value='authorsort' i18n>Author: A to Z</option>
+ <option value='authorsort.descending' i18n>Author: Z to A</option>
+ </optgroup>
+ <optgroup label="Sort by Publication Date" i18n-label>
+ <option value='pubdate' i18n>Date: A to Z</option>
+ <option value='pubdate.descending' i18n>Date: Z to A</option>
+ </optgroup>
+ <optgroup label="Sort by Popularity" i18n-label>
+ <option value='popularity' i18n>Most Popular</option>
+ <option value='poprel' i18n>Popularity Adjusted Relevance</option>
+ </optgroup>
+ </select>
+ <div class="checkbox pl-2 ml-2">
+ <label>
+ <input type="checkbox" [(ngModel)]="searchContext.available"/>
+ <span class="pl-1" i18n>Limit to Available</span>
+ </label>
+ </div>
+ <div class="checkbox pl-3">
+ <label>
+ <input type="checkbox" [disabled]="true"
+ [(ngModel)]="searchContext.isMetarecord"/>
+ <span class="pl-1" i18n>Group Formats/Editions</span>
+ </label>
+ </div>
+ <div class="checkbox pl-3">
+ <label>
+ <input type="checkbox" [(ngModel)]="searchContext.global"/>
+ <span class="pl-1" i18n>Show Results from All Libraries</span>
+ </label>
+ </div>
+ </div>
+ </div>
+ <div class="row mt-3" *ngIf="showFilters()">
+ <div class="col-lg-3">
<select class="form-control" multiple="true"
[(ngModel)]="searchContext.ccvmFilters.item_type">
<option value='' i18n>All Item Types</option>
value="{{itemType.code()}}">{{itemType.value()}}</option>
</select>
</div>
- <div class="col-lg-2">
+ <div class="col-lg-3">
<select class="form-control" multiple="true"
[(ngModel)]="searchContext.ccvmFilters.item_form">
<option value='' i18n>All Item Forms</option>
value="{{itemForm.code()}}">{{itemForm.value()}}</option>
</select>
</div>
- <div class="col-lg-2">
+ <div class="col-lg-3">
<select class="form-control"
[(ngModel)]="searchContext.ccvmFilters.item_lang" multiple="true">
<option value='' i18n>All Languages</option>
value="{{lang.code()}}">{{lang.value()}}</option>
</select>
</div>
- <div class="col-lg-2">
+ <div class="col-lg-3">
<select class="form-control"
[(ngModel)]="searchContext.ccvmFilters.audience" multiple="true">
<option value='' i18n>All Audiences</option>
</select>
</div>
</div>
- <div class="row pt-2">
- <div class="col-lg-2">
+ <div class="row mt-3" *ngIf="showFilters()">
+ <div class="col-lg-3">
<select class="form-control"
[(ngModel)]="searchContext.ccvmFilters.vr_format" multiple="true">
<option value='' i18n>All Video Formats</option>
value="{{vrFormat.code()}}">{{vrFormat.value()}}</option>
</select>
</div>
- <div class="col-lg-2">
+ <div class="col-lg-3">
<select class="form-control"
[(ngModel)]="searchContext.ccvmFilters.bib_level" multiple="true">
<option value='' i18n>All Bib Levels</option>
value="{{bibLevel.code()}}">{{bibLevel.value()}}</option>
</select>
</div>
- <div class="col-lg-2">
+ <div class="col-lg-3">
<select class="form-control"
[(ngModel)]="searchContext.ccvmFilters.lit_form" multiple="true">
<option value='' i18n>All Literary Forms</option>
value="{{litForm.code()}}">{{litForm.value()}}</option>
</select>
</div>
- <div class="col-lg-2">
- <ng-container *ngIf="copyLocations.length > 0">
- <select class="form-control"
- [(ngModel)]="searchContext.copyLocations" multiple="true">
- <option value='' i18n>All Copy Locations</option>
- <option *ngFor="let loc of copyLocations" value="{{loc.id()}}" i18n>
- {{loc.name()}} ({{orgName(loc.owning_lib())}})
+ <div class="col-lg-3">
+ <select class="form-control"
+ [(ngModel)]="searchContext.copyLocations" multiple="true">
+ <option value='' i18n>All Copy Locations</option>
+ <option *ngFor="let loc of copyLocations" value="{{loc.id()}}" i18n>
+ {{loc.name()}} ({{orgName(loc.owning_lib())}})
</option>
- </select>
- </ng-container>
+ </select>
</div>
</div>
</ng-template>
</ngb-tab>
<ngb-tab title="Numeric Search" i18n-title id="ident">
<ng-template ngbTabContent>
- <div class="row mt-3">
+ <div class="row mt-4">
<div class="col-lg-12">
<div class="form-inline">
<label for="ident-type" i18n>Query Type</label>
<option i18n disabled value="cnbrowse">Call Number (Shelf Browse)</option>
<option i18n value="identifier|lccn">LCCN</option>
<option i18n value="identifier|tcn">TCN</option>
- <option i18n disabled value="item_barcode">Item Barcode</option>
+ <option i18n value="item_barcode">Item Barcode</option>
</select>
<label for="ident-value" class="ml-2" i18n>Value</label>
<input name="ident-value" id='ident-query-input'
type="text" class="form-control ml-2"
[(ngModel)]="searchContext.identQuery"
- (keyup.enter)="formEnter('ident')"
+ (keyup.enter)="searchByForm()"
placeholder="Numeric Query..."/>
<button class="btn btn-success ml-2" type="button"
[disabled]="searchIsActive()"
- (click)="formEnter('ident')" i18n>Search</button>
+ (click)="searchByForm()" i18n>Search</button>
</div>
</div>
</div>
</ngb-tab>
<ngb-tab title="MARC Search" i18n-title id="marc">
<ng-template ngbTabContent>
- <div class="row mt-3">
+ <div class="row mt-4">
<div class="col-lg-12">
<div class="form-inline mt-2"
*ngFor="let q of searchContext.marcValue; let idx = index; trackBy:trackByIdx">
<label for="marc-tag-{{idx}}" i18n>Tag</label>
- <input class="form-control ml-2" size="3" type="text" name="marc-tag-{{idx}}"
- id="{{ idx == 0 ? 'first-marc-tag' : '' }}"
- [(ngModel)]="searchContext.marcTag[idx]"/>
+ <input class="form-control ml-2" size="3" type="text"
+ name="marc-tag-{{idx}}" id="{{ idx == 0 ? 'first-marc-tag' : '' }}"
+ [(ngModel)]="searchContext.marcTag[idx]"
+ (keyup.enter)="searchByForm()"/>
<label for="marc-subfield-{{idx}}" class="ml-2" i18n>Subfield</label>
- <input class="form-control ml-2" size="1" type="text" name="marc-subfield-{{idx}}"
- [(ngModel)]="searchContext.marcSubfield[idx]"/>
+ <input class="form-control ml-2" size="1" type="text"
+ name="marc-subfield-{{idx}}"
+ [(ngModel)]="searchContext.marcSubfield[idx]"
+ (keyup.enter)="searchByForm()"/>
<label for="marc-value-{{idx}}" class="ml-2" i18n>Value</label>
<input class="form-control ml-2" type="text" name="marc-value-{{idx}}"
- [(ngModel)]="searchContext.marcValue[idx]"/>
+ [(ngModel)]="searchContext.marcValue[idx]"
+ (keyup.enter)="searchByForm()"/>
<button class="btn btn-sm material-icon-button ml-2"
(click)="addMarcSearchRow(idx + 1)">
<span class="material-icons">add_circle_outline</span>
<span class="material-icons">remove_circle_outline</span>
</button>
<button *ngIf="idx == 0" class="btn btn-success ml-2"
- (click)="formEnter('marc')" i18n>Submit</button>
+ (click)="searchByForm()" i18n>Submit</button>
</div>
</div>
</div>
</ngb-tab>
</ngb-tabset>
</div>
+ <div class="col-lg-4">
+ <div class="row">
+ <div class="col-lg-12">
+ <div class="float-right d-flex">
+ <eg-org-select
+ (onChange)="orgOnChange($event)"
+ [initialOrg]="searchContext.searchOrg"
+ [placeholder]="'Library'" >
+ </eg-org-select>
+ <button class="btn btn-success mr-1 ml-1" type="button"
+ [disabled]="searchIsActive()"
+ (click)="searchContext.pager.offset=0;searchByForm()" i18n>
+ Search
+ </button>
+ <button class="btn btn-warning mr-1" type="button"
+ [disabled]="searchIsActive()"
+ (click)="searchContext.reset()" i18n>
+ Reset Form
+ </button>
+ <button class="btn btn-info ml-1" type="button"
+ (click)="goToBrowse()" i18n>Browse</button>
+ </div>
+ </div>
+ </div>
+ <div class="row mt-2">
+ <div class="col-lg-12">
+ <eg-catalog-basket-actions></eg-catalog-basket-actions>
+ </div>
+ </div>
+ </div>
</div>
searchContext: CatalogSearchContext;
ccvmMap: {[ccvm: string]: IdlObject[]} = {};
cmfMap: {[cmf: string]: IdlObject} = {};
- showAdvancedSearch = false;
+ showSearchFilters = false;
copyLocations: IdlObject[];
searchTab: string;
//@ViewChild('searchTabs') searchTabs: NgbTabset;
private staffCat: StaffCatalogService
) {
this.copyLocations = [];
- this.searchTab = 'filters';
+ this.searchTab = 'term';
}
ngOnInit() {
// Start with advanced search options open
// if any filters are active.
- this.showAdvancedSearch = this.hasAdvancedOptions();
+ this.showSearchFilters = this.filtersActive();
}
ngAfterViewInit() {
if (st === 'marc' || st === 'ident') {
this.searchTab = st;
} else {
- this.searchTab = 'filters';
+ this.searchTab = 'term';
}
});
* Display the advanced/extended search options when asked to
* or if any advanced options are selected.
*/
- showAdvanced(): boolean {
- return this.showAdvancedSearch;
+ showFilters(): boolean {
+ return this.showSearchFilters;
}
- toggleAdvancedSearch() {
- this.showAdvancedSearch = !this.showAdvancedSearch;
+ toggleFilters() {
+ this.showSearchFilters = !this.showSearchFilters;
this.refreshCopyLocations();
}
- hasAdvancedOptions(): boolean {
+ filtersActive(): boolean {
if (this.searchContext.copyLocations[0] !== '') { return true; }
- if (this.searchContext.identQuery) { return true; }
- if (this.searchContext.marcValue[0] !== '') { return true; }
// ccvm filters may be present without any filters applied.
// e.g. if filters were applied then removed.
}
refreshCopyLocations() {
- if (!this.showAdvanced()) { return; }
+ if (!this.showFilters()) { return; }
// TODO: is this how we avoid displaying too many locations?
const org = this.searchContext.searchOrg;
this.searchContext.marcValue.splice(index, 1);
}
- formEnter(source) {
+ searchByForm(): void {
+ // Starting a new search
this.searchContext.pager.offset = 0;
- // Form searches override basket displays.
+ // Trim the search context to necessary data only depending
+ // on which tab the user is on, i.e. which type of search
+ // the user is requesting.
+
+ // A form search overrides an existing basket display request
this.searchContext.basket = null;
- switch (source) {
+ switch (this.searchTab) {
- case 'query': // main search form query input
+ case 'term': // main search form query input
// Be sure a previous ident search does not take precedence
// over the new term query submitted via Enter within
break;
}
- this.searchByForm();
+ this.staffCat.search();
}
// https://stackoverflow.com/questions/42322968/angular2-dynamic-input-field-lose-focus-when-input-changes
return index;
}
- searchByForm(): void {
- this.staffCat.search();
- }
searchIsActive(): boolean {
return this.searchContext.searchState === CatalogSearchState.SEARCHING;