LPXXX Angular patron search component
authorBill Erickson <berickxx@gmail.com>
Thu, 9 Jan 2020 23:13:12 +0000 (18:13 -0500)
committerBill Erickson <berickxx@gmail.com>
Thu, 9 Jan 2020 23:13:12 +0000 (18:13 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/staff/share/patron/search.component.html
Open-ILS/src/eg2/src/app/staff/share/patron/search.component.ts

index 919ecb0..18d64c9 100644 (file)
@@ -5,16 +5,31 @@
 
     <div class="col-lg-2">
       <input class="form-control" type="text" id='focus-this-input'
-        i18n-aria-label aria-label="Last Name"
+        i18n-aria-label aria-label="Last Name" (keyup.enter)="go()"
         i18n-placeholder placeholder="Last Name"
-        [(ngModel)]="search.au.family_name"/>
+        [(ngModel)]="search.family_name"/>
     </div>
 
-    <div class="col-lg-2"></div>
-    <div class="col-lg-2"></div>
-    <div class="col-lg-2"></div>
     <div class="col-lg-2">
-      <button class="btn btn-success" (click)="performSearch()" i18n>Search</button>
+      <input class="form-control" type="text" (keyup.enter)="go()"
+        i18n-aria-label aria-label="First Name"
+        i18n-placeholder placeholder="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()"
+        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()"
+        i18n-placeholder placeholder="Name Keywords"
+        [(ngModel)]="search.name"/>
+    </div>
+    <div class="col-lg-2">
+      <button class="btn btn-success" (click)="go()" i18n>Search</button>
     </div>
     <div class="col-lg-2"></div>
   </div>
   <eg-grid #searchGrid idlClass="au" [dataSource]="dataSource"
     [showDeclaredFieldsOnly]="true" persistKey="circ.patron.search">
 
-    <eg-grid-column path='id'></eg-grid-column>      
-    <eg-grid-column path='card.barcode'></eg-grid-column>
-    <eg-grid-column path='profile.name'></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">
       [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="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>
+
index b884dc2..dba36c3 100644 (file)
@@ -1,7 +1,8 @@
 import {Component, Input, Output, OnInit, AfterViewInit,
     EventEmitter, ViewChild, Renderer2} from '@angular/core';
 import {Observable, of} from 'rxjs';
-import {IdlService} from '@eg/core/idl.service';
+import {map} from 'rxjs/operators';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
 import {EventService} from '@eg/core/event.service';
 import {NetService} from '@eg/core/net.service';
 import {AuthService} from '@eg/core/auth.service';
@@ -14,6 +15,19 @@ import {GridComponent} from '@eg/share/grid/grid.component';
 import {GridDataSource} from '@eg/share/grid/grid';
 import {Pager} from '@eg/share/util/pager';
 
+const DEFAULT_SORT = [
+   "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"
+];
+
 @Component({
   selector: 'eg-patron-search',
   templateUrl: './search.component.html'
@@ -24,25 +38,7 @@ export class PatronSearchComponent implements OnInit, AfterViewInit {
     @ViewChild('searchGrid', {static: false}) searchGrid: GridComponent;
     @Output() patronsSelected: EventEmitter<any>;
 
-    search = {
-        au: {},
-        aua: {},
-        include_inactive: false
-    };
-
-    searchSort = [
-        "family_name ASC",
-        "first_given_name ASC",
-        "second_given_name ASC",
-        "dob DESC"
-    ];
-
-    searchFlesh = [
-        "card", "settings", "standing_penalties", "addresses",
-        "billing_address", "mailing_address", "stat_cat_entries",
-        "waiver_entries", "usr_activity", "notes", "profile"
-    ];
-
+    search: any = {};
     dataSource: GridDataSource;
 
     constructor(
@@ -69,27 +65,39 @@ export class PatronSearchComponent implements OnInit, AfterViewInit {
         this.patronsSelected.emit(rows);
     }
 
+    go() {
+        this.searchGrid.reload();
+    }
+
     getRows(pager: Pager, sort: any[]): Observable<any> {
 
         const search = this.compileSearch();
         if (!search) { return of(); }
 
+        const sorter = this.compileSort(sort);
+
         return this.net.request(
             'open-ils.actor',
             'open-ils.actor.patron.search.advanced.fleshed',
             this.auth.token(),
             this.compileSearch(),
             pager.limit,
-            this.searchSort,
-            null, // todo?
+            sorter,
+            null, // ?
             this.auth.user().ws_ou(),
-            this.searchFlesh,
+            DEFAULT_FLESH,
             pager.offset
-        );
+        ).pipe(map(user => this.localFleshUser(user)));
     }
 
-    isValue(val: any): boolean {
-        return (val !== null && val !== undefined && val !== '');
+    localFleshUser(user: IdlObject): IdlObject {
+        user.home_ou(this.org.get(user.home_ou()));
+        return user;
+    }
+
+    compileSort(sort: any[]): string[] {
+        if (!sort || sort.length === 0) { return DEFAULT_SORT; }
+        return sort.map(def => `${def.name} ${def.dir}`);
     }
 
     compileSearch(): any {
@@ -97,19 +105,51 @@ export class PatronSearchComponent implements OnInit, AfterViewInit {
         let hasSearch = false;
         const search: Object = {};
 
-        Object.keys(this.search.au).forEach(field => {
-            const val = this.search.au[field];
+        Object.keys(this.search).forEach(field => {
+            const val = this.search[field];
+
             if (this.isValue(val)) {
                 hasSearch = true;
-                search[field] = {value: val, group: 0}
+                search[field] = this.mapSearchField(field, val);
             }
+
         });
 
         return hasSearch ? search : null;
     }
 
-    performSearch() {
-        this.searchGrid.reload();
+    isValue(val: any): boolean {
+        return (val !== null && val !== undefined && val !== '');
+    }
+
+    mapSearchField(field: string, value: any): any {
+
+        const chunk = {value: value, group: 0};
+
+        switch (field) {
+            case 'name':
+                delete chunk.group;
+                break;
+
+            case 'phone': // thunk
+            case 'ident':
+                chunk.group = 2;
+                break;
+
+            case 'street1':
+            case 'street2':
+            case 'city':
+            case 'state':
+            case 'post_code':
+                chunk.group = 1;
+                break;
+
+            case 'card':
+                chunk.group = 3;
+                break;
+        }
+
+        return chunk;
     }
 }