web staff : remaining patron search fields
authorBill Erickson <berick@esilibrary.com>
Tue, 10 Dec 2013 20:35:48 +0000 (15:35 -0500)
committerBill Erickson <berick@esilibrary.com>
Tue, 10 Dec 2013 20:35:48 +0000 (15:35 -0500)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/patron/t_search.tt2
Open-ILS/src/templates/staff/circ/patron/t_search_results.tt2
Open-ILS/src/templates/staff/css/style.css.tt2
Open-ILS/src/templates/staff/t_navbar.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/app.js
Open-ILS/web/js/ui/default/staff/services/idl.js

index 083d2f9..eb65e4e 100644 (file)
@@ -1,17 +1,63 @@
 
 <br/><br/> <!-- css -->
+
 <div class="row">
   <div class="col-lg-10">
-    <form ng-submit="search(args)">
-      <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 -->
+    <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>
+      </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>
+      <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>
+      <div class="row">
+        <div class="col-lg-12">
+          <input type="text" ng-model="args.state" 
+            placeholder="[% l('State') %]" title="[% l('State') %]"/>
+          <input type="text" ng-model="args.post_code" 
+            placeholder="[% l('Post Code') %]" title="[% l('Post Code') %]"/>
+
+          <!-- typeaheads for profile group and org unit -->
+
+          <input type="text" 
+            placeholder="[% l('Profile Group') %]"
+            ng-model="selecedProfileName"
+            typeahead="grp.name for grp in profiles | filter:$viewValue" 
+            typeahead-on-select="args.profile=$item.id"
+            typeahead-editable="false" />
+
+          <input type="text" 
+            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"
+            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>
     </form>
   </div>
   <div class="col-lg-2 text-right">
index 054a98a..2200316 100644 (file)
@@ -18,6 +18,7 @@ COLUMNS = [
 {label => l('First Name'),  name => 'first_given_name', display => 1},
 {label => l('Middle Name'), name => 'second_given_name',display => 1},
 {label => l('DoB'),         name => 'dob',              display => 1},
+{label => l('Home Library'),name => 'home_ou.shortname',display => 1},
 {label => l('Created On'),  name => 'create_date',      display => 1},
 
 {label => l('Mailing:Street 1'), name => 'mailing_address.street1', display => 1},
index 620cba9..e31c0c2 100644 (file)
@@ -83,6 +83,9 @@ table.list tr.selected td {
     background-color: #F5F5F5;
 }
 
+
+/* TODO: move these to patron CSS file ---  */
+
 /** style to make a grid look like a striped table */
 #patron-summary-grid div.row {padding: 3px;}
 #patron-summary-grid div.row:nth-child(odd) {background-color: rgb(249, 249, 249);}
@@ -94,3 +97,13 @@ 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 {
+  margin-bottom: 5px;
+}
+
+#patron-search-form select, input[type="text"], 
+  input[type="submit"],input[type="reset"] {
+  width: 10em;
+}
+
+
index f9508cc..b06ebc5 100644 (file)
@@ -58,7 +58,9 @@
       <!-- cataloging -->
       <li class="dropdown">
         <a href="javascript:;" class="dropdown-toggle" 
-          data-toggle="dropdown">[% l('Cataloging') %]<b class="caret"></b></a>
+          data-toggle="dropdown">[% l('Cataloging') %]
+            <b class="caret"></b>
+        </a>
         <ul class="dropdown-menu">
           <li>
             <a href="./cat/bucket/record/view" target="_self">
index 73f2681..4f25b08 100644 (file)
@@ -27,7 +27,16 @@ angular.module('egPatronApp', ['ngRoute', 'ui.bootstrap',
             .then(function(settings) { egEnv.aous = settings });
         }
 
+        egEnv.classLoaders.pgt = function() {
+            return egPCRUD.search('pgt', {parent : null}, 
+                {flesh : -1, flesh_fields : {pgt : ['children']}}
+            ).then(
+                function(tree) {egEnv.absorbTree(tree, 'pgt')}
+            );
+        }
+
         egEnv.loadClasses.push('aous');
+        egEnv.loadClasses.push('pgt');
 
         // app-globally modify the default flesh fields for 
         // fleshed user retrieval
@@ -219,15 +228,24 @@ function($scope,  $q,  $filter,  egNet,  egAuth,  egUser,  patronSvc,  egEnv,  e
  * Manages patron search
  */
 .controller('PatronSearchCtrl',
-       ['$scope','$q','$routeParams','$timeout','$window','$location',
+       ['$scope','$q','$routeParams','$timeout','$window','$location','egEnv',
        '$filter','egIDL','egNet','egAuth','egEvent','egList','egUser','patronSvc',
-function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  
+function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egEnv,
         $filter,  egIDL,  egNet,  egAuth,  egEvent,  egList,  egUser,  patronSvc) {
 
     $scope.initTab('search');
     $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...
+    $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.
@@ -246,6 +264,7 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,
         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.match(/phone|ident/)) {
                 search[key].group = 2;
@@ -261,8 +280,8 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,
     }
 
     // send compiled search; get user IDs
-    function sendSearch(search) {
-        search = compileSearch(search);
+    function sendSearch(args) {
+        search = compileSearch(args);
         egNet.request(
             'open-ils.actor',
             'open-ils.actor.patron.search.advanced',
@@ -273,8 +292,8 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,
                 "second_given_name ASC",
                 "dob DESC"
             ],
-            null, /* TODO: OU filter */
-            search.inactive
+            args.inactive,
+            args.home_ou
 
         ).then(function(ids) {
             retrieveUsers(ids);
@@ -286,6 +305,7 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,
         angular.forEach(ids, function(id, idx) {
             // capture idx to maintain search results order
             egUser.get(id).then(function(user) {
+                patronSvc.localFlesh(user);
                 $scope.patrons.items[idx] = user;
             });
         });
index 3d88924..9b55937 100644 (file)
@@ -57,6 +57,18 @@ angular.module('egCoreMod')
             mkclass(cls, service.classes[cls].fields);
     };
 
+    service.toHash = function(obj) {
+        var hash = {};
+        angular.forEach(
+            service.classes[obj.classname].fields, 
+            function(field) { 
+                if (field.virtual) return;
+                hash[field.name] = obj[field.name]() 
+            }
+        )
+        return hash;
+    }
+
     return service;
 }]);