web staff: more patron saerch
authorBill Erickson <berick@esilibrary.com>
Wed, 11 Dec 2013 16:08:15 +0000 (11:08 -0500)
committerBill Erickson <berick@esilibrary.com>
Wed, 11 Dec 2013 16:08:15 +0000 (11:08 -0500)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/patron/index.tt2
Open-ILS/src/templates/staff/circ/patron/t_search.tt2
Open-ILS/src/templates/staff/css/style.css.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/app.js

index 1130edf..235ca4f 100644 (file)
@@ -37,7 +37,7 @@
         <a href="./circ/patron/{{patron().id()}}/edit">[% l('Edit') %]</a>
       </li>
       <li ng-class="{active : tab == 'search'}" class="pull-right">
-        <a href="./circ/patron/search">[% l('Search') %]</a>
+        <a href="./circ/patron/search">[% l('Patron Search') %]</a>
       </li>
     </ul>
     <div class="tab-content">
index eb65e4e..ff97a2f 100644 (file)
@@ -3,60 +3,63 @@
 
 <div class="row">
   <div class="col-lg-10">
-    <form ng-submit="search(args)" id="patron-search-form">
-      <div class="row">
-        <div class="col-lg-12">
-          <input type="text" ng-model="args.card" placeholder="[% l('Barcode') %]" focus-me="focusMe"/>
-          <input type="text" ng-model="args.family_name" placeholder="[% l('Last Name') %]"/>
-          <input type="text" ng-model="args.first_given_name" placeholder="[% l('First Name') %]"/>
-          <input type="submit" value="[% l('Search') %]"/>
-          <input type="reset" value="[% l('Clear Form') %]"/>
-          <!-- " trick vim -->
-        </div>
+    <form ng-submit="search(args)" id="patron-search-form" role="form" class="form-inline">
+      <div class="form-group">
+
+        <!-- TODO: inputs need sr-only labels
+           <label class="sr-only" for="input-id">label</label>
+        -->
+        <input type="text" class="form-control" ng-model="args.card" placeholder="[% l('Barcode') %]" focus-me="focusMe"/>
+        <input type="text" class="form-control" ng-model="args.family_name" placeholder="[% l('Last Name') %]"/>
+        <input type="text" class="form-control" ng-model="args.first_given_name" placeholder="[% l('First Name') %]"/>
+        <input type="submit" class="btn btn-default" value="[% l('Search') %]"/>
+        <input type="reset" class="btn btn-default" value="[% l('Clear Form') %]"/>
+
+        <button class="btn btn-default" ng-click="applyShowExtras($event, true)" 
+          title="[% l('Show More Fields') %]" ng-show="!showExtras">
+          <span class="glyphicon glyphicon-circle-arrow-down"></span></button>
+        <button class="btn btn-default" ng-click="applyShowExtras($event, false)" 
+          title="[% l('Show Fewer Fields') %]" ng-show="showExtras">
+          <span class="glyphicon glyphicon-circle-arrow-up"></span></button>
       </div>
-      <div class="row">
-        <div class="col-lg-12">
-          <input type="text" ng-model="args.alias" placeholder="[% l('Alias') %]"/>
-          <input type="text" ng-model="args.usrname" placeholder="[% l('Username') %]"/>
-          <input type="text" ng-model="args.email" placeholder="[% l('Email') %]"/>
-          <input type="text" ng-model="args.ident" placeholder="[% l('Identification') %]"/>
-        </div>
+      <div class="form-group" ng-show="showExtras">
+        <input type="text" class="form-control" ng-model="args.second_given_name" placeholder="[% l('Middle Name') %]"/>
+        <input type="text" class="form-control" ng-model="args.alias" placeholder="[% l('Alias') %]"/>
+        <input type="text" class="form-control" ng-model="args.usrname" placeholder="[% l('Username') %]"/>
+        <input type="text" class="form-control" ng-model="args.email" placeholder="[% l('Email') %]"/>
+        <input type="text" class="form-control" ng-model="args.ident" placeholder="[% l('Identification') %]"/>
       </div>
-      <div class="row">
-        <div class="col-lg-12">
-          <input type="text" ng-model="args.id" placeholder="[% l('Database ID') %]"/>
-          <input type="text" ng-model="args.phone" placeholder="[% l('Phone') %]"/>
-          <input type="text" ng-model="args.street1" placeholder="[% l('Street 1') %]"/>
-          <input type="text" ng-model="args.street2" placeholder="[% l('Street 2') %]"/>
-          <input type="text" ng-model="args.city" placeholder="[% l('City') %]"/>
-        </div>
+      <div class="form-group" ng-show="showExtras">
+        <input type="text" class="form-control" ng-model="args.id" placeholder="[% l('Database ID') %]"/>
+        <input type="text" class="form-control" ng-model="args.phone" placeholder="[% l('Phone') %]"/>
+        <input type="text" class="form-control" ng-model="args.street1" placeholder="[% l('Street 1') %]"/>
+        <input type="text" class="form-control" ng-model="args.street2" placeholder="[% l('Street 2') %]"/>
+        <input type="text" class="form-control" ng-model="args.city" placeholder="[% l('City') %]"/>
       </div>
-      <div class="row">
-        <div class="col-lg-12">
-          <input type="text" ng-model="args.state" 
+      <div class="form-group" ng-show="showExtras">
+          <input type="text" class="form-control" ng-model="args.state" 
             placeholder="[% l('State') %]" title="[% l('State') %]"/>
-          <input type="text" ng-model="args.post_code" 
+          <input type="text" class="form-control" ng-model="args.post_code" 
             placeholder="[% l('Post Code') %]" title="[% l('Post Code') %]"/>
 
-          <!-- typeaheads for profile group and org unit -->
-
-          <input type="text" 
+          <input type="text" class="form-control"  
             placeholder="[% l('Profile Group') %]"
-            ng-model="selecedProfileName"
-            typeahead="grp.name for grp in profiles | filter:$viewValue" 
-            typeahead-on-select="args.profile=$item.id"
+            ng-model="args.profile"
+            typeahead="grp as grp.name for grp in profiles | filter:$viewValue" 
             typeahead-editable="false" />
 
-          <input type="text" 
+          <input type="text" class="form-control" 
             placeholder="[% l('Home Library') %]"
-            ng-model="selecedLibraryCode"
-            typeahead="org.shortname for org in org_units | filter:$viewValue" 
-            typeahead-on-select="args.home_ou=$item.id"
+            ng-model="args.home_ou"
+            typeahead="org as org.shortname for org in org_units | filter:$viewValue" 
             typeahead-editable="false" />
 
-          <input type="checkbox" ng-model="args.inactive" id="patron-search-inactive"/> 
-          <label for="patron-search-inactive">[% l('Include Inactive?') %]</label>
-        </div>
+          <div class="checkbox">
+            <label>
+              <input type="checkbox" ng-model="args.inactive">
+              [% l('Include Inactive?') %]
+            </label>
+          </div>
       </div>
     </form>
   </div>
index e31c0c2..cfc65af 100644 (file)
@@ -97,7 +97,7 @@ but the ones I'm finding aren't quite cutting it..*/
 .pad-vert {padding : 20px 0px 10px 0px;}
 #patron-checkout-barcode { width: 18em; }
 
-#patron-search-form div.row {
+#patron-search-form div.form-group {
   margin-bottom: 5px;
 }
 
index 4f25b08..48840da 100644 (file)
@@ -237,15 +237,16 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egEnv,
     $scope.focusMe = true;
     $scope.patrons = patronSvc.patrons;
 
-    // typeahead doesn't filter correct with full hash objects,
-    // so trim them down to just name and id.  I'm probably 
-    // missing something...
+    // typeahead doesn't filter correctly with full hash objects, so
+    // trim them down to just name and id.  This would allow us to use
+    // full objects (egIDL.toHash()) instead of manually creating 
+    // objects...  maybe later.
+    // http://stackoverflow.com/questions/18429967/angularjs-ui-typeahead-match-on-leading-characters
     $scope.profiles = egEnv.pgt.list.map(
         function(grp) {return {name : grp.name(), id : grp.id() }})
 
     $scope.org_units = egEnv.aou.list.map(
         function(org) {return {shortname : org.shortname(), id : org.id() }})
-        
 
     // TODO: experiment
     // if this is useful, it should be moved into a service.
@@ -259,13 +260,30 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egEnv,
         // TODO: function to reset all tips
     };
 
+    // TODO:
+    // another experiment -- user prefs in localStorage -- this should
+    // be a service, which can also check (certain) user/org settings
+    $scope.applyShowExtras = function($event, bool) {
+        $scope.showExtras = bool;
+        $window.localStorage.setItem('eg.prefs.circ.patron.search.showExtras', bool);
+        $event.preventDefault();
+    }
+    // localStorage stores strings; parse the values as JSON bools
+    $scope.showExtras = JSON.parse($window.localStorage.getItem(
+        'eg.prefs.circ.patron.search.showExtras')) || false;
+
     // map form arguments into search params
     function compileSearch(args) {
         var search = {};
         angular.forEach(args, function(val, key) {
             if (!val) return;
-            if (key.match(/home_ou|inactive/)) return; // separate API param
-            search[key] = {value : val, group : 0};
+            if (key == 'profile') {
+                search.profile = {value : args.profile.id, group : 0};
+            } else if (key == 'home_ou') {
+                search.home_ou = args.home_ou.id; // passed separately
+            } else {
+                search[key] = {value : val, group : 0};
+            }
             if (key.match(/phone|ident/)) {
                 search[key].group = 2;
             } else {
@@ -276,12 +294,20 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egEnv,
                 }
             }
         });
+
         return search;
     }
 
     // send compiled search; get user IDs
     function sendSearch(args) {
         search = compileSearch(args);
+
+        var home_ou = search.home_ou;
+        delete search.home_ou;
+        var inactive = search.inactive;
+        delete search.inactive;
+
+        console.debug('patron search ' + js2JSON(search));
         egNet.request(
             'open-ils.actor',
             'open-ils.actor.patron.search.advanced',
@@ -292,8 +318,8 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egEnv,
                 "second_given_name ASC",
                 "dob DESC"
             ],
-            args.inactive,
-            args.home_ou
+            inactive,
+            home_ou
 
         ).then(function(ids) {
             retrieveUsers(ids);