items out; alt list display
authorBill Erickson <berick@esilibrary.com>
Wed, 2 Jul 2014 16:19:34 +0000 (12:19 -0400)
committerBill Erickson <berick@esilibrary.com>
Wed, 2 Jul 2014 16:19:34 +0000 (12:19 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/circ/patron/t_items_out.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js

index 6113065..71fc1a0 100644 (file)
@@ -1,10 +1,31 @@
 <!-- items out list -->
 
+<div ng-if="show_alt_circs">
+  <!-- only show the main vs. alt circ list tabs if the alt
+      circ list is meant to display -->
+  <ul class="nav nav-tabs">
+    <li ng-class="{active : items_out_display == 'main'}">
+      <a href ng-click="show_main_list()">
+        [% l('Items Checked Out') %] ({{main_list.length}})
+      </a>
+    </li>
+    <li ng-class="{active : items_out_display == 'alt'}">
+      <a href ng-click="show_alt_list()">
+        [% l('Other/Special Circulations') %] ({{alt_list.length}})
+      </a>
+    </li>
+  </ul>
+</div>
+<div ng-if="!show_alt_circs" class="strong-text-2">
+  [% l('Items Checked Out') %]
+</div>
+
+<div class="tab-content">
+  <div class="tab-pane active">
 <eg-grid
   idl-class="circ"
   id-field="id"
   features="-sort,-multisort"
-  main-label="[% l('Items Checked Out') %]"
   items-provider="gridDataProvider"
   persist-key="circ.patron.items_out">
 
@@ -48,4 +69,5 @@
   <eg-grid-field path="target_copy.call_number.record.*" hidden></eg-grid-field>
   <eg-grid-field path="target_copy.call_number.record.simple_record.*" hidden></eg-grid-field>
 </eg-grid>
-
+  </div>
+</div>
index 75c8c2f..297f2d2 100644 (file)
@@ -2,36 +2,82 @@
  * List of patron items checked out
  */
 
-angular.module('egPatronApp').controller('PatronItemsOutCtrl',
+angular.module('egPatronApp')
 
+.controller('PatronItemsOutCtrl',
        ['$scope','$q','$routeParams','egCore','egUser','patronSvc',
         'egGridDataProvider','$modal','egCirc','egConfirmDialog','egBilling',
 function($scope,  $q,  $routeParams,  egCore , egUser,  patronSvc , 
          egGridDataProvider , $modal , egCirc , egConfirmDialog , egBilling) {
-
     $scope.initTab('items_out', $routeParams.id);
 
-    patronSvc.items_out = []; 
-    patronSvc.items_out_ids = [];
+    // cache of circ objects for grid display
+    patronSvc.items_out = [];
+
+    // main list of checked out items
+    $scope.main_list = [];
 
-    // Items out display settings.  These are laoded in .configure().
-    // NOTE: UI only supports one list, so anything configured to show
-    // in the 'bottom' list will not presently display.
+    // list of alt circs (lost, etc.) and/or check-in with fines circs
+    $scope.alt_list = []; 
+
+    // these are fetched during startup (i.e. .configure())
+    // By default, show lost/lo/cr items in the alt list
     var display_lost = Number(
         egCore.env.aous['ui.circ.items_out.lost']) || 2;
     var display_lo = Number(
-        egCore.env.aous['ui.circ.items_out.longoverdue']) || 1;
+        egCore.env.aous['ui.circ.items_out.longoverdue']) || 2;
     var display_cr = Number(
         egCore.env.aous['ui.circ.items_out.claimsreturned']) || 2;
 
+    var fetch_checked_in = true;
+    $scope.show_alt_circs = true;
+    if (display_lost & 4 && display_lo & 4 && display_cr & 4) {
+        // all special types are configured to be hidden once
+        // checked in, so there's no need to fetch checked-in circs.
+        fetch_checked_in = false;
+
+        if (display_lost & 1 && display_lo & 1 && display_cr & 1) {                 
+            // additionally, if all types are configured to display    
+            // in the main list while checked out, nothing will         
+            // ever appear in the alternate list, so we can hide          
+            // the alternate list from the UI.  
+            $scope.show_alt_circs = false;
+        }
+    }
+
+    $scope.items_out_display = 'main';
+    $scope.show_main_list = function() {
+        // don't need a full reset_page() to swap tabs
+        $scope.items_out_display = 'main';
+        patronSvc.items_out = [];
+        provider.refresh();
+    }
+
+    $scope.show_alt_list = function() {
+        // don't need a full reset_page() to swap tabs
+        $scope.items_out_display = 'alt';
+        patronSvc.items_out = [];
+        provider.refresh();
+    }
+
+    // Reload the user to pick up changes in items out, fines, etc.
+    // Reload circs since the contents of the main vs. alt list may
+    // have changed.
+    function reset_page() {
+        patronSvc.refreshPrimary();
+        patronSvc.items_out = []; 
+        $scope.main_list = [];
+        $scope.alt_list = [];
+        provider.refresh() 
+    }
+
     var provider = egGridDataProvider.instance({});
     $scope.gridDataProvider = provider;
 
-    function fetchCircs(offset, count) {
+    function fetch_circs(id_list, offset, count) {
 
         // fetch the lot of circs and stream the results back via notify
-        return egCore.pcrud.search('circ', 
-            {id : patronSvc.items_out_ids},
+        return egCore.pcrud.search('circ', {id : id_list},
             {   flesh : 4,
                 flesh_fields : {
                     circ : ['target_copy'],
@@ -43,7 +89,7 @@ function($scope,  $q,  $routeParams,  egCore , egUser,  patronSvc ,
                 // fields on the bre to select.  More may be needed.
                 // note that fleshed fields are explicitly selected.
                 select : { bre : ['id'] },
-                limit : count,
+                limit  : count,
                 offset : offset,
                 // we need an order-by to support paging
                 order_by : {circ : ['xact_start']} 
@@ -65,67 +111,79 @@ function($scope,  $q,  $routeParams,  egCore , egUser,  patronSvc ,
         });
     }
 
+    // decide which list each circ belongs to
+    function promote_circs(list, display_code, open) {
+        if (open) {                                                    
+            if (1 & display_code) { // bitflag 1 == top list                   
+                $scope.main_list = $scope.main_list.concat(list);
+            } else {                                                   
+                $scope.alt_list = $scope.alt_list.concat(list);
+            }                                                          
+        } else {                                                       
+            if (4 & display_code) return;  // bitflag 4 == hide on checkin     
+            $scope.alt_list = $scope.alt_list.concat(list);
+        } 
+    }
+
+    // fetch IDs for circs we care about
+    function get_circ_ids() {
+        $scope.main_list = [];
+        $scope.alt_list = [];
+
+        // we can fetch these in parallel
+        var promise1 = egCore.net.request(
+            'open-ils.actor',
+            'open-ils.actor.user.checked_out.authoritative',
+            egCore.auth.token(), $scope.patron_id
+        ).then(function(outs) {
+            $scope.main_list = outs.out.concat(outs.overdue);
+            promote_circs(outs.lost, display_lost, true);                            
+            promote_circs(outs.long_overdue, display_lo, true);             
+            promote_circs(outs.claims_returned, display_cr, true);
+        });
+
+        // only fetched checked-in-with-bills circs if configured to display
+        var promise2 = !fetch_checked_in ? $q.when() : egCore.net.request(
+            'open-ils.actor',
+            'open-ils.actor.user.checked_in_with_fines.authoritative',
+            egCore.auth.token(), $scope.patron_id
+        ).then(function(outs) {
+            promote_circs(outs.lost, display_lost);
+            promote_circs(outs.long_overdue, display_lo);
+            promote_circs(outs.claims_returned, display_cr);
+        });
+
+        return $q.all([promise1, promise2]);
+    }
+
     provider.get = function(offset, count) {
 
+        var id_list = $scope[$scope.items_out_display + '_list'];
+
         // see if we have the requested range cached
         if (patronSvc.items_out[offset]) {
             return provider.arrayNotifier(
                 patronSvc.items_out, offset, count);
         }
 
-        // see if we have the circ IDs for this range already loaded
-        if (patronSvc.items_out_ids[offset]) {
-            return fetchCircs(offset, count);
+        // See if we have the circ IDs for this range already loaded.
+        // this would happen navigating to a subsequent page.
+        if (id_list[offset]) {
+            return fetch_circs(id_list, offset, count);
         }
 
-
-        // avoid returning the request directly so the caller so the
+        // avoid returning the request directly to the caller so the
         // notify()'s from egCore.net.request don't leak into the 
         // final set of notifies (i.e. the real responses);
 
         var deferred = $q.defer();
-        patronSvc.items_out_ids = [];
+        get_circ_ids().then(function() {
 
-        egCore.net.request(
-            'open-ils.actor',
-            'open-ils.actor.user.checked_out.authoritative',
-            egCore.auth.token(), $scope.patron_id
-
-        ).then(function(outs) {
-
-            patronSvc.items_out_ids = outs.out.concat(outs.overdue);
-
-            // When rendering the items still checked out list, only
-            // show "alternate" circulations whose bitmask is 1 
-            // (i.e. has a value of 1 or 5).
-
-            if (display_lo & 1) {
-                patronSvc.items_out_ids = 
-                    patronSvc.items_out_ids.concat(outs.long_overdue);
-            }
-
-            if (display_lost & 1) {
-                patronSvc.items_out_ids = 
-                    patronSvc.items_out_ids.concat(outs.lost);
-            }
-
-            if (display_cr & 1) {
-                patronSvc.items_out_ids = 
-                    patronSvc.items_out_ids.concat(outs.claims_returned);
-            }
-
-            // no item out
-            if (!patronSvc.items_out_ids.length) {
-                deferred.resolve();
-                return;
-            }
+            id_list = $scope[$scope.items_out_display + '_list'];
 
             // relay the notified circs back to the grid through our promise
-            fetchCircs(offset, count).then(
-                deferred.resolve,
-                null, 
-                deferred.notify
-            );
+            fetch_circs(id_list, offset, count).then(
+                deferred.resolve, null, deferred.notify);
         });
 
         return deferred.promise;
@@ -218,15 +276,6 @@ function($scope,  $q,  $routeParams,  egCore , egUser,  patronSvc ,
         });
     }
 
-    // Reload the user to pick up changes in items out, fines, etc.
-    // Reload circs since LOST, etc. items may no longer be applicable for display.
-    function reset_page() {
-        patronSvc.refreshPrimary();
-        patronSvc.items_out = []; 
-        patronSvc.items_out_ids = [];
-        provider.refresh() 
-    }
-
     function batch_action_with_barcodes(items, action) {
         if (!items.length) return;
         var barcodes = items.map(function(circ)