import {NgModule} from '@angular/core';
import {StaffCommonModule} from '@eg/staff/common.module';
import {GridModule} from '@eg/share/grid/grid.module';
-import {PatronService} from './patron.service'
+import {PatronService} from './patron.service';
import {PatronSearchComponent} from './search.component';
+import {ProfileSelectComponent} from './profile-select.component';
@NgModule({
declarations: [
- PatronSearchComponent
+ PatronSearchComponent,
+ ProfileSelectComponent
],
imports: [
StaffCommonModule,
GridModule
],
exports: [
- PatronSearchComponent
+ PatronSearchComponent,
+ ProfileSelectComponent
],
providers: [
PatronService
--- /dev/null
+
+<eg-combobox #combobox
+ [startId]="initialValue" [entries]="cboxEntries"
+ (onChange)="propagateCboxChange($event)"
+ i18n-placeholder placeholder="Profile Group">
+</eg-combobox>
--- /dev/null
+import {Component, Input, Output, OnInit,
+ EventEmitter, ViewChild, forwardRef} from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
+import {Observable, of} from 'rxjs';
+import {map} from 'rxjs/operators';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
+import {OrgService} from '@eg/core/org.service';
+import {AuthService} from '@eg/core/auth.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {ComboboxEntry, ComboboxComponent
+ } from '@eg/share/combobox/combobox.component';
+
+/* User permission group select comoboxbox.
+ *
+ * <eg-profile-select
+ * [(ngModel)]="pgtObject" [useDisplayEntries]="true">
+ * </eg-profile-select>
+ */
+
+// Use a unicode char for spacing instead of ASCII=32 so the browser
+// won't collapse the nested display entries down to a single space.
+const PAD_SPACE = ' '; // U+2007
+
+@Component({
+ selector: 'eg-profile-select',
+ templateUrl: './profile-select.component.html',
+ providers: [{
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => ProfileSelectComponent),
+ multi: true
+ }]
+})
+export class ProfileSelectComponent implements ControlValueAccessor, OnInit {
+
+ // If true, attempt to build the selector from
+ // permission.grp_tree_display_entry's for the current org unit.
+ // If false OR if no permission.grp_tree_display_entry's exist
+ // build the selector from the full permission.grp_tree
+ @Input() useDisplayEntries: boolean;
+
+ // Emits the selected 'pgt' object or null if the selector is cleared.
+ @Output() profileChange: EventEmitter<IdlObject>;
+
+ @ViewChild('combobox', {static: false}) cbox: ComboboxComponent;
+
+ initialValue: number;
+ cboxEntries: ComboboxEntry[] = [];
+ profiles: {[id: number]: IdlObject} = {};
+
+ // Stub functions required by ControlValueAccessor
+ propagateChange = (_: any) => {};
+ propagateTouch = () => {};
+
+ constructor(
+ private org: OrgService,
+ private auth: AuthService,
+ private pcrud: PcrudService) {
+ this.profileChange = new EventEmitter<IdlObject>();
+ }
+
+ ngOnInit() {
+ this.collectGroups().then(grps => this.sortGroups(grps));
+ }
+
+ collectGroups(): Promise<IdlObject[]> {
+
+ if (!this.useDisplayEntries) {
+ return this.fetchPgt();
+ }
+
+ return this.pcrud.search('pgtde',
+ {org: this.org.ancestors(this.auth.user().ws_ou(), true)},
+ {flesh: 1, flesh_fields: {'pgtde': ['grp']}},
+ {atomic: true}
+
+ ).toPromise().then(groups => {
+
+ if (groups.length === 0) { return this.fetchPgt(); }
+
+ // In the query above, we fetch display entries for our org
+ // unit plus ancestors. However, we only want to use one
+ // collection of display entries, those owned at our org
+ // unit or our closest ancestor.
+ let closestOrg = this.org.get(groups[0].org());
+ groups.forEach(g => {
+ const org = this.org.get(g.org());
+ if (closestOrg.ou_type().depth() < org.ou_type().depth()) {
+ closestOrg = org;
+ }
+ });
+ groups = groups.filter(g => g.org() === closestOrg.id());
+
+ // Link the display entry to its pgt.
+ const pgtList = [];
+ groups.forEach(display => {
+ const pgt = display.grp();
+ pgt._display = display;
+ pgtList.push(pgt);
+ });
+
+ return pgtList;
+ });
+ }
+
+ fetchPgt(): Promise<IdlObject[]> {
+ return this.pcrud.retrieveAll('pgt', {}, {atomic: true}).toPromise();
+ }
+
+ grpLabel(groups: IdlObject[], grp: IdlObject): string {
+ let tmp = grp;
+ let depth = 0;
+
+ do {
+ const pid = tmp._display ? tmp._display.parent() : tmp.parent();
+ if (!pid) { break; } // top of the tree
+
+ // Should always produce a value unless a perm group
+ // display tree is poorly structured.
+ tmp = groups.filter(g => g.id() === pid)[0];
+
+ depth++;
+
+ } while (tmp);
+
+ return PAD_SPACE.repeat(depth) + grp.name();
+ }
+
+ sortGroups(groups: IdlObject[], grp?: IdlObject) {
+ if (!grp) {
+ grp = groups.filter(g => g.parent() === null)[0];
+ }
+
+ this.profiles[grp.id()] = grp;
+ this.cboxEntries.push(
+ {id: grp.id(), label: this.grpLabel(groups, grp)});
+
+ groups.filter(g => g.parent() === grp.id())
+ .forEach(child => this.sortGroups(groups, child));
+ }
+
+ writeValue(pgt: IdlObject) {
+ const id = pgt ? pgt.id() : null;
+ if (this.cbox) {
+ this.cbox.selectedId = id;
+ } else {
+ // Will propagate to cbox after its instantiated.
+ this.initialValue = id;
+ }
+ }
+
+ registerOnChange(fn) {
+ this.propagateChange = fn;
+ }
+
+ registerOnTouched(fn) {
+ this.propagateTouch = fn;
+ }
+
+ propagateCboxChange(entry: ComboboxEntry) {
+ if (entry) {
+ const grp = this.profiles[entry.id];
+ this.propagateChange(grp);
+ this.profileChange.emit(grp);
+ } else {
+ this.profileChange.emit(null);
+ this.propagateChange(null);
+ }
+ }
+}
+
-
<div class="patron-search-form">
- <div class="row">
-
+ <div class="row mb-2">
<div class="col-lg-2">
<input class="form-control" type="text" id='focus-this-input'
i18n-aria-label aria-label="Last Name" (keyup.enter)="go()"
i18n-placeholder placeholder="Last Name"
[(ngModel)]="search.family_name"/>
</div>
-
<div class="col-lg-2">
<input class="form-control" type="text" (keyup.enter)="go()"
i18n-aria-label aria-label="First Name"
[(ngModel)]="search.first_given_name"/>
</div>
<div class="col-lg-2">
- <input class="form-control" type="text" id='focus-this-input'
- i18n-aria-label aria-label="Middle Name" (keyup.enter)="go()"
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Middle Name"
i18n-placeholder placeholder="Middle Name"
[(ngModel)]="search.second_given_name"/>
</div>
<div class="col-lg-2">
- <input class="form-control" type="text" id='focus-this-input'
- i18n-aria-label aria-label="Name Keywords" (keyup.enter)="go()"
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Name Keywords"
i18n-placeholder placeholder="Name Keywords"
[(ngModel)]="search.name"/>
</div>
<div class="col-lg-2">
<button class="btn btn-success" (click)="go()" i18n>Search</button>
+ <button (click)="toggleExpandForm()"
+ class="btn btn-outline-dark ml-2 label-with-material-icon"
+ i18n-title title="Toggle Expanded Form Display">
+ <span *ngIf="!expandForm" class="material-icons">arrow_drop_down</span>
+ <span *ngIf="expandForm" class="material-icons">arrow_drop_up</span>
+ </button>
+ </div>
+ <div class="col-lg-2">
</div>
- <div class="col-lg-2"></div>
- </div>
- <div class="row mt-2">
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- </div>
- <div class="row mt-2">
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- </div>
- <div class="row mt-2">
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- </div>
- <div class="row mt-2">
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
- <div class="col-lg-2"></div>
</div>
+
+ <ng-container *ngIf="expandForm">
+ <div class="row mb-2">
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Barcode"
+ i18n-placeholder placeholder="Barcode"
+ [(ngModel)]="search.barcode"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Alias"
+ i18n-placeholder placeholder="Alias"
+ [(ngModel)]="search.alias"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Username"
+ i18n-placeholder placeholder="Username"
+ [(ngModel)]="search.usrname"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Email"
+ i18n-placeholder placeholder="Email"
+ [(ngModel)]="search.email"/>
+ </div>
+ <div class="col-lg-2">
+ <button class="btn btn-warning" (click)="clear()" i18n>Clear Form</button>
+ </div>
+ <div class="col-lg-2">
+ </div>
+ </div>
+ <div class="row mb-2">
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Identification"
+ i18n-placeholder placeholder="Identification"
+ [(ngModel)]="search.ident"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Phone"
+ i18n-placeholder placeholder="Phone"
+ [(ngModel)]="search.phone"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Street 1"
+ i18n-placeholder placeholder="Street 1"
+ [(ngModel)]="search.street1"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Street 2"
+ i18n-placeholder placeholder="Street 2"
+ [(ngModel)]="search.street2"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="City"
+ i18n-placeholder placeholder="City"
+ [(ngModel)]="search.city"/>
+ </div>
+ <div class="col-lg-2"></div>
+ </div>
+ <div class="row mb-2">
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="State"
+ i18n-placeholder placeholder="State"
+ [(ngModel)]="search.state"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Post Code"
+ i18n-placeholder placeholder="Post Code"
+ [(ngModel)]="search.post_code"/>
+ </div>
+ <div class="col-lg-2">
+ <eg-profile-select [useDisplayEntries]="true"
+ [(ngModel)]="search.profile">
+ </eg-profile-select>
+ <!-- profile -->
+ </div>
+ <div class="col-lg-2">
+ <!-- home org -->
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Guardian"
+ i18n-placeholder placeholder="Guardian"
+ [(ngModel)]="search.guardian"/>
+ </div>
+ <div class="col-lg-2"></div>
+ </div>
+ <div class="row mb-2">
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="DOB Year"
+ i18n-placeholder placeholder="DOB Year"
+ [(ngModel)]="search.dob_year"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="DOB Month"
+ i18n-placeholder placeholder="DOB Month"
+ [(ngModel)]="search.dob_month"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="DOB Day"
+ i18n-placeholder placeholder="DOB Day"
+ [(ngModel)]="search.dob_day"/>
+ </div>
+ <div class="col-lg-2">
+ <input class="form-control" type="text" (keyup.enter)="go()"
+ i18n-aria-label aria-label="Database ID"
+ i18n-placeholder placeholder="Database ID"
+ [(ngModel)]="search.id"/>
+ </div>
+ <div class="col-lg-2">
+ <div class="form-check form-check-inline">
+ <input class="form-check-input" type="checkbox"
+ (change)="toggleIncludeInactive()"
+ id="include-inactive" [(ngModel)]="search.inactive">
+ <label class="form-check-label" for="include-inactive" i18n>
+ Include Inactive
+ ?</label>
+ </div>
+ </div>
+ <div class="col-lg-2"></div>
+ </div>
+ </ng-container><!-- expand form -->
</div>
<div class="patron-search-grid">
- <eg-grid #searchGrid idlClass="au" [dataSource]="dataSource"
- [showDeclaredFieldsOnly]="true" persistKey="circ.patron.search">
+ <eg-grid #searchGrid idlClass="au"
+ persistKey="circ.patron.search"
+ (onRowActivate)="rowsSelected($event)"
+ [dataSource]="dataSource"
+ [showDeclaredFieldsOnly]="true">
- <eg-grid-column path='id' i18n-label label="ID"></eg-grid-column>
- <eg-grid-column path='card.barcode' i18n-label label="Card"></eg-grid-column>
- <eg-grid-column path='profile.name' i18n-label label="Profile">
- </eg-grid-column>
- <eg-grid-column path='family_name' [sortable]="true" [multiSortable]="true">
- </eg-grid-column>
- <eg-grid-column path='first_given_name' [sortable]="true" [multiSortable]="true">
- </eg-grid-column>
- <eg-grid-column path='second_given_name' [sortable]="true" [multiSortable]="true">
- </eg-grid-column>
- <eg-grid-column path='dob' [sortable]="true" [multiSortable]="true">
- </eg-grid-column>
- <eg-grid-column path='home_ou.shortname' i18n-label label="Home Library">
- </eg-grid-column>
- <eg-grid-column path='create_date' i18n-label label="Created On"
- [sortable]="true" [multiSortable]="true">
- </eg-grid-column>
+ <eg-grid-column path='id'
+ i18n-label label="ID"></eg-grid-column>
+ <eg-grid-column path='card.barcode'
+ i18n-label label="Card"></eg-grid-column>
+ <eg-grid-column path='profile.name'
+ i18n-label label="Profile"></eg-grid-column>
+ <eg-grid-column path='family_name'
+ [sortable]="true" [multiSortable]="true"></eg-grid-column>
+ <eg-grid-column path='first_given_name'
+ [sortable]="true" [multiSortable]="true"></eg-grid-column>
+ <eg-grid-column path='second_given_name'
+ [sortable]="true" [multiSortable]="true"></eg-grid-column>
+ <eg-grid-column path='dob'
+ [sortable]="true" [multiSortable]="true"></eg-grid-column>
+ <eg-grid-column path='home_ou.shortname'
+ i18n-label label="Home Library"></eg-grid-column>
+ <eg-grid-column path='create_date' i18n-label label="Created On"
+ [sortable]="true" [multiSortable]="true"></eg-grid-column>
- <eg-grid-column i18n-label label="Mailing:Street 1" path='mailing_address.street1' visible></eg-grid-column>
- <eg-grid-column i18n-label label="Mailing:Street 2" path='mailing_address.street2'></eg-grid-column>
- <eg-grid-column i18n-label label="Mailing:City" path='mailing_address.city'></eg-grid-column>
- <eg-grid-column i18n-label label="Mailing:County" path='mailing_address.county'></eg-grid-column>
- <eg-grid-column i18n-label label="Mailing:State" path='mailing_address.state'></eg-grid-column>
- <eg-grid-column i18n-label label="Mailing:Zip" path='mailing_address.post_code'></eg-grid-column>
+ <eg-grid-column i18n-label label="Mailing:Street 1"
+ path='mailing_address.street1' visible></eg-grid-column>
+ <eg-grid-column i18n-label label="Mailing:Street 2"
+ path='mailing_address.street2'></eg-grid-column>
+ <eg-grid-column i18n-label label="Mailing:City"
+ path='mailing_address.city'></eg-grid-column>
+ <eg-grid-column i18n-label label="Mailing:County"
+ path='mailing_address.county'></eg-grid-column>
+ <eg-grid-column i18n-label label="Mailing:State"
+ path='mailing_address.state'></eg-grid-column>
+ <eg-grid-column i18n-label label="Mailing:Zip"
+ path='mailing_address.post_code'></eg-grid-column>
- <eg-grid-column i18n-label label="Billing:Street 1" path='billing_address.street1'></eg-grid-column>
- <eg-grid-column i18n-label label="Billing:Street 2" path='billing_address.street2'></eg-grid-column>
- <eg-grid-column i18n-label label="Billing:City" path='billing_address.city'></eg-grid-column>
- <eg-grid-column i18n-label label="Billing:County" path='billing_address.county'></eg-grid-column>
- <eg-grid-column i18n-label label="Billing:State" path='billing_address.state'></eg-grid-column>
- <eg-grid-column i18n-label label="Billing:Zip" path='billing_address.post_code'></eg-grid-column>
-
+ <eg-grid-column i18n-label label="Billing:Street 1"
+ path='billing_address.street1'></eg-grid-column>
+ <eg-grid-column i18n-label label="Billing:Street 2"
+ path='billing_address.street2'></eg-grid-column>
+ <eg-grid-column i18n-label label="Billing:City"
+ path='billing_address.city'></eg-grid-column>
+ <eg-grid-column i18n-label label="Billing:County"
+ path='billing_address.county'></eg-grid-column>
+ <eg-grid-column i18n-label label="Billing:State"
+ path='billing_address.state'></eg-grid-column>
+ <eg-grid-column i18n-label label="Billing:Zip"
+ path='billing_address.post_code'></eg-grid-column>
</eg-grid>
+
</div>
import {AuthService} from '@eg/core/auth.service';
import {OrgService} from '@eg/core/org.service';
import {PcrudService} from '@eg/core/pcrud.service';
+import {ServerStoreService} from '@eg/core/server-store.service';
import {ToastService} from '@eg/share/toast/toast.service';
import {StringComponent} from '@eg/share/string/string.component';
import {ComboboxEntry, ComboboxComponent} from '@eg/share/combobox/combobox.component';
import {Pager} from '@eg/share/util/pager';
const DEFAULT_SORT = [
- "family_name ASC",
- "first_given_name ASC",
- "second_given_name ASC",
- "dob DESC"
+ 'family_name ASC',
+ 'first_given_name ASC',
+ 'second_given_name ASC',
+ 'dob DESC'
];
const DEFAULT_FLESH = [
- "card", "settings", "standing_penalties", "addresses", "billing_address",
- "mailing_address", "stat_cat_entries", "waiver_entries", "usr_activity",
- "notes", "profile"
+ 'card', 'settings', 'standing_penalties', 'addresses', 'billing_address',
+ 'mailing_address', 'stat_cat_entries', 'waiver_entries', 'usr_activity',
+ 'notes', 'profile'
];
+const EXPAND_FORM = 'eg.circ.patron.search.show_extras';
+const INCLUDE_INACTIVE = 'eg.circ.patron.search.include_inactive';
+
@Component({
selector: 'eg-patron-search',
templateUrl: './search.component.html'
@Output() patronsSelected: EventEmitter<any>;
search: any = {};
+ searchOrg: number;
+ expandForm: boolean;
dataSource: GridDataSource;
+ profileGroups: IdlObject[] = [];
constructor(
private renderer: Renderer2,
private net: NetService,
private org: OrgService,
- private auth: AuthService
+ private auth: AuthService,
+ private store: ServerStoreService
) {
this.patronsSelected = new EventEmitter<any>();
this.dataSource = new GridDataSource();
}
ngOnInit() {
+ this.searchOrg = this.org.root().id();
+ this.store.getItemBatch([EXPAND_FORM, INCLUDE_INACTIVE])
+ .then(settings => {
+ this.expandForm = settings[EXPAND_FORM];
+ this.search.inactive = settings[INCLUDE_INACTIVE];
+ });
}
ngAfterViewInit() {
this.renderer.selectRootElement('#focus-this-input').focus();
}
- rowsSelected(rows: any) {
- this.patronsSelected.emit(rows);
+ toggleExpandForm() {
+ this.expandForm = !this.expandForm;
+ if (this.expandForm) {
+ this.store.setItem(EXPAND_FORM, true);
+ } else {
+ this.store.removeItem(EXPAND_FORM);
+ }
+ }
+
+ toggleIncludeInactive() {
+ if (this.search.inactive) { // value set by ngModel
+ this.store.setItem(INCLUDE_INACTIVE, true);
+ } else {
+ this.store.removeItem(INCLUDE_INACTIVE);
+ }
+ }
+
+ rowsSelected(rows: IdlObject | IdlObject[]) {
+ this.patronsSelected.emit([].concat(rows));
}
go() {
this.searchGrid.reload();
}
+ clear() {
+ this.search = {};
+ this.searchOrg = this.org.root().id();
+ }
+
+ homeOrgChange(orgId: number) {
+ this.searchOrg = orgId;
+ }
+
getRows(pager: Pager, sort: any[]): Observable<any> {
+ let observable: Observable<IdlObject>;
+
+ if (this.search.id) {
+ observable = this.searchById();
+ } else {
+ observable = this.searchByForm(pager, sort);
+ }
+
+ return observable.pipe(map(user => this.localFleshUser(user)));
+ }
+
+ localFleshUser(user: IdlObject): IdlObject {
+ user.home_ou(this.org.get(user.home_ou()));
+ return user;
+ }
+
+ searchByForm(pager: Pager, sort: any[]): Observable<IdlObject> {
+
const search = this.compileSearch();
if (!search) { return of(); }
pager.limit,
sorter,
null, // ?
- this.auth.user().ws_ou(),
+ this.searchOrg,
DEFAULT_FLESH,
pager.offset
- ).pipe(map(user => this.localFleshUser(user)));
+ );
}
- localFleshUser(user: IdlObject): IdlObject {
- user.home_ou(this.org.get(user.home_ou()));
- return user;
+ searchById(): Observable<IdlObject> {
+ return this.net.request(
+ 'open-ils.actor',
+ 'open-ils.actor.user.fleshed.retrieve',
+ this.auth.token(), this.search.id, DEFAULT_FLESH
+ );
}
compileSort(sort: any[]): string[] {
const search: Object = {};
Object.keys(this.search).forEach(field => {
- const val = this.search[field];
-
- if (this.isValue(val)) {
- hasSearch = true;
- search[field] = this.mapSearchField(field, val);
- }
-
+ search[field] = this.mapSearchField(field);
+ if (search[field]) { hasSearch = true; }
});
return hasSearch ? search : null;
return (val !== null && val !== undefined && val !== '');
}
- mapSearchField(field: string, value: any): any {
+ mapSearchField(field: string): any {
+
+ const value = this.search[field];
+ if (!this.isValue(value)) { return null; }
const chunk = {value: value, group: 0};
switch (field) {
- case 'name':
- delete chunk.group;
- break;
- case 'phone': // thunk
- case 'ident':
- chunk.group = 2;
+ case 'name': // name keywords
+ case 'inactive':
+ delete chunk.group;
break;
case 'street1':
chunk.group = 1;
break;
+ case 'phone':
+ case 'ident':
+ chunk.group = 2;
+ break;
+
case 'card':
chunk.group = 3;
break;
+
+ case 'profile':
+ chunk.group = 5;
+ chunk.value = chunk.value.id(); // pgt object
+ break;
+
+ case 'dob_day':
+ case 'dob_month':
+ case 'dob_year':
+ chunk.group = 4;
+ chunk.value = chunk.value.replace(/\D/g, '');
+
+ if (!field.match(/year/)) {
+ // force day/month to be 2 digits
+ chunk[field].value = ('0' + value).slice(-2);
+ }
+ break;
}
+ // Confirm the value wasn't scrubbed away above
+ if (!this.isValue(chunk.value)) { return null; }
+
return chunk;
}
}
line-height: inherit;
}
+.mat-icon-shrunk-in-button {
+ line-height: inherit;
+ font-size: 18px;
+}
+
.input-group .mat-icon-in-button {
font-size: .88rem !important; /* useful for buttons that cuddle up with inputs */
}