patron search selectors; results grid dbl click
authorBill Erickson <berick@esilibrary.com>
Mon, 16 Jun 2014 15:07:49 +0000 (11:07 -0400)
committerBill Erickson <berick@esilibrary.com>
Mon, 16 Jun 2014 15:07:49 +0000 (11:07 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/patron/t_search.tt2
Open-ILS/src/templates/staff/css/circ/patron.css.tt2
Open-ILS/src/templates/staff/share/t_autogrid.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/app.js
Open-ILS/web/js/ui/default/staff/services/ui.js

index fab7e5c..29abb40 100644 (file)
         </div>
 
         <div class="col-md-2">
+          <!--
           <input type="text" class="form-control"  
             placeholder="[% l('Profile Group') %]"
             ng-model="searchArgs.profile"
             typeahead="grp as grp.name for grp in profiles | filter:$viewValue" 
             typeahead-editable="false" />
-        </div>
-
-        <div class="col-md-2">
-          <input type="text" class="form-control" 
-            placeholder="[% l('Home Library') %]"
-            ng-model="searchArgs.home_ou"
-            typeahead="org as org.shortname for org in org_units | filter:$viewValue" 
-            typeahead-editable="false" />
+            -->
+
+            <div class="btn-group patron-search-selector" dropdown>
+              <button type="button" class="btn btn-default dropdown-toggle">
+                <span style="padding-right: 5px;">{{searchArgs.profile.name() || "[% l('Profile Group') %]"}}</span>
+                <span class="caret"></span>
+              </button>
+              <ul class="dropdown-menu">
+                <li ng-repeat="grp in profiles">
+                  <a href dropdown-toggle
+                    style="padding-left: {{pgt_depth(grp) * 10 + 5}}px"
+                    ng-click="searchArgs.profile = grp">{{grp.name()}}</a>
+                </li>
+              </ul>
+            </div>
+        </div>
+
+        <div class="col-md-2">
+          <eg-org-selector label="[% l('Home Library') %]" 
+            selected="searchArgs.home_ou">
+          </eg-org-selector>
         </div>
 
         <div class="col-md-2">
index f81b787..6628c8f 100644 (file)
@@ -18,6 +18,13 @@ but the ones I'm finding aren't quite cutting it..*/
 #patron-search-form-row {margin-left: 0px;}
 #patron-search-form div.col-md-2 { padding: 2px; }
 #patron-search-form input:not([type="checkbox"]) { width: 100%; }
+#patron-search-form .eg-org-selector,
+#patron-search-form .eg-org-selector button,
+#patron-search-form .patron-search-selector,
+  #patron-search-form .patron-search-selector button { 
+  width: 100%; 
+  text-align: left
+}
 
 
 #patron-payments-spreadsheet {
index 8c8c6ff..5e5568d 100644 (file)
       </div>
       <div class="eg-grid-cell eg-grid-cell-content"
           ng-click="handleRowClick($event, item)"
+          ng-dblclick="gridControls.activateItem(item)"
           ng-repeat="col in columns"
           style="flex:{{col.flex}}"
           ng-show="col.visible">
index 00f6888..a02b001 100644 (file)
@@ -28,6 +28,7 @@ angular.module('egPatronApp', ['ngRoute', 'ui.bootstrap',
             ]).then(function(settings) { egCore.env.aous = settings });
         }
 
+        // local stat cats are displayed in the summary bar on each page.
         egCore.env.classLoaders.actsc = function() {
             return egCore.pcrud.search('actsc', 
                 {owner : egCore.org.ancestors(
@@ -189,6 +190,7 @@ function($q , $timeout , $location , egCore,  egUser , $locale) {
         service.holds = [];
         service.hold_ids = [];
         service.checkout_overrides = {};
+        service.patron_stats = null;
         service.hasAlerts = false;
         service.alertsShown = false;
         service.patronExpired = false;
@@ -197,8 +199,40 @@ function($q , $timeout , $location , egCore,  egUser , $locale) {
     }
     service.resetPatronLists();  // initialize
 
-    // sets the default user, fetching as necessary
-    service.setDefault = function(id, user, force) {
+    // sets the primary display user, fetching data as necessary.
+    service.setPrimary = function(id, user, force) {
+        var user_id = id ? id : (user ? user.id() : null);
+
+        console.debug('setting primary user to: ' + user_id);
+
+        // avoid running multiple retrievals for the same patron, which
+        // can happen during dbl-click by maintaining a single running
+        // data retrieval promise
+        if (service.primaryUserPromise) {
+            if (service.primaryUserId == user_id) {
+                return service.primaryUserPromise.promise;
+            } else {
+                service.primaryUserPromise = null;
+            }
+        }
+
+        service.primaryUserPromise = $q.defer();
+        service.primaryUserId = user_id;
+
+        service.getPrimary(id, user, force)
+        .then(function() {
+            var p = service.primaryUserPromise;
+            service.primaryUserId = null;
+            // clear before resolution just to be safe.
+            service.primaryUserPromise = null;
+            p.resolve();
+        });
+
+        return service.primaryUserPromise.promise;
+    }
+
+    service.getPrimary = function(id, user, force) {
+
         if (user) {
             if (!force && service.current && 
                 service.current.id() == user.id()) {
@@ -460,7 +494,7 @@ function($scope,  $q,  $location , $filter,  egCore,  egUser,  patronSvc) {
 
         if (patron_id) {
             $scope.patron_id = patron_id;
-            return patronSvc.setDefault($scope.patron_id)
+            return patronSvc.setPrimary($scope.patron_id)
             .then(function() {return patronSvc.checkAlerts()})
             .then(redirectToAlertPanel);
         }
@@ -476,7 +510,7 @@ function($scope,  $q,  $location , $filter,  egCore,  egUser,  patronSvc) {
        ['$scope','$location','egCore','egConfirmDialog','egUser','patronSvc',
 function($scope , $location , egCore , egConfirmDialog , egUser , patronSvc) {
     $scope.selectMe = true; // focus text input
-    patronSvc.setDefault(); // clear the default user
+    patronSvc.setPrimary(); // clear the default user
 
     // jump to the patron checkout UI
     function loadPatron(user_id) {
@@ -596,7 +630,7 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
         function() {return $scope.gridControls.selectedItems()},
         function(list) {
             if (list[0]) 
-                patronSvc.setDefault(null, list[0]);
+                patronSvc.setPrimary(null, list[0]);
         },
         true
     );
@@ -687,23 +721,24 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
     $scope.patronSearchGridProvider = provider;
 
     if (egCore.env.pgt) {
-        $scope.profiles = egCore.env.pgt.list.map(
-            function(grp) {return {name : grp.name(), id : grp.id() }})
+        $scope.profiles = egCore.env.pgt.list;
     } else {
-
         egCore.pcrud.search('pgt', {parent : null}, 
             {flesh : -1, flesh_fields : {pgt : ['children']}}
         ).then(
             function(tree) {
                 egCore.env.absorbTree(tree, 'pgt')
-                $scope.profiles = egCore.env.pgt.list.map(
-                    function(grp) {return {name : grp.name(), id : grp.id() }})
+                $scope.profiles = egCore.env.pgt.list;
             }
         );
     }
 
-    $scope.org_units = egCore.env.aou.list.map(
-        function(org) {return {shortname : org.shortname(), id : org.id() }})
+    // determine the tree depth of the profile group
+    $scope.pgt_depth = function(grp) {
+        var d = 0;
+        while (grp = egCore.env.pgt.map[grp.parent()]) d++;
+        return d;
+    }
 
     $scope.applyShowExtras = function($event, bool) {
         $scope.showExtras = bool;
@@ -720,10 +755,9 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
         angular.forEach(args, function(val, key) {
             if (!val) return;
             if (key == 'profile') {
-                search.profile = {value : args.profile.id, group : 0};
-                //search.profile = {value : search.profile, group : 0};
+                search.profile = {value : args.profile.id(), group : 0};
             } else if (key == 'home_ou') {
-                search.home_ou = args.home_ou.id; // passed separately
+                search.home_ou = args.home_ou.id(); // passed separately
             } else if (key == 'inactive') {
                 search.inactive = val;
             } else {
@@ -919,7 +953,7 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
                     activeGrid.refresh();
                     // force a refresh of the user, since they may now
                     // have blocking penalties, etc.
-                    patronSvc.setDefault(patronSvc.current.id(), null, true);
+                    patronSvc.setPrimary(patronSvc.current.id(), null, true);
                 });
             }
         );
@@ -958,7 +992,7 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
                     activeGrid.refresh();
                     // force a refresh of the user, since they may now
                     // have blocking penalties, etc.
-                    patronSvc.setDefault(patronSvc.current.id(), null, true);
+                    patronSvc.setPrimary(patronSvc.current.id(), null, true);
                 });
             }
         );
index 9ee72c7..6278f98 100644 (file)
@@ -189,6 +189,7 @@ function($modal, $interpolate) {
     return {
         restrict : 'AE',
         transclude : true,
+        replace : true, // makes styling easier
         scope : {
             selected : '=', // defaults to workstation or root org
             
@@ -196,11 +197,14 @@ function($modal, $interpolate) {
             // any org units where the response value is true, the
             // org unit will not be added to the selector.
             hiddenTest : '=',
+
+            // optional primary drop-down button label
+            label : '@'
         },
 
         // any reason to move this into a TT2 template?
         template : 
-            '<div class="btn-group" dropdown>'
+            '<div class="btn-group eg-org-selector" dropdown>'
             + '<button type="button" class="btn btn-default dropdown-toggle">'
              + '<span style="padding-right: 5px;">{{getSelectedName()}}</span>'
              + '<span class="caret"></span>'
@@ -231,19 +235,13 @@ function($modal, $interpolate) {
             $scope.getSelectedName = function() {
                 if ($scope.selected)
                     return $scope.selected.shortname();
+                return $scope.label;
             }
 
             $scope.orgChanged = function(org) {
+                console.log('here with ' + org);
                 $scope.selected = egOrg.get(org.id);
             }
-
-            if (!$scope.selected) {
-                // apply a default value if none provided
-                $scope.selected = 
-                    egAuth.workstation() ?
-                    egOrg.get(egAuth.workstation().owning_lib()) :
-                    egOrg.tree();
-            }
         }]
     }
 })