more grid standarizing
authorBill Erickson <berick@esilibrary.com>
Tue, 10 Jun 2014 19:42:23 +0000 (15:42 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 10 Jun 2014 19:42:47 +0000 (15:42 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
18 files changed:
Open-ILS/src/templates/staff/cat/bucket/record/t_pending.tt2
Open-ILS/src/templates/staff/cat/bucket/record/t_search.tt2
Open-ILS/src/templates/staff/cat/bucket/record/t_view.tt2
Open-ILS/src/templates/staff/circ/patron/t_bill_history_payments.tt2
Open-ILS/src/templates/staff/circ/patron/t_bill_history_xacts.tt2
Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
Open-ILS/src/templates/staff/circ/patron/t_messages.tt2
Open-ILS/src/templates/staff/circ/patron/t_xact_details.tt2
Open-ILS/web/js/ui/default/staff/cat/bucket/record/app.js
Open-ILS/web/js/ui/default/staff/cat/item/app.js
Open-ILS/web/js/ui/default/staff/circ/checkin/app.js
Open-ILS/web/js/ui/default/staff/circ/in_house_use/app.js
Open-ILS/web/js/ui/default/staff/circ/patron/app.js
Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
Open-ILS/web/js/ui/default/staff/circ/patron/checkout.js
Open-ILS/web/js/ui/default/staff/circ/patron/holds.js
Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js
Open-ILS/web/js/ui/default/staff/services/grid.js

index 13aee3e..eefc60a 100644 (file)
@@ -1,5 +1,6 @@
 <eg-grid
   ng-hide="forbidden"
+  features="-sort,-multisort"
   id-field="id"
   idl-class="rmsr"
   auto-fields="true"
index 0117fbc..684b139 100644 (file)
@@ -30,7 +30,7 @@
   id-field="id"
   idl-class="rmsr"
   auto-fields="true"
-  query="gridQuery"
+  grid-controls="gridControls"
   menu-label="[% l('Buckets') %]"
   persist-key="cat.bucket.record.search">
 
index bdf6bfb..d3d95d3 100644 (file)
@@ -3,7 +3,7 @@
   id-field="id"
   idl-class="rmsr"
   auto-fields="true"
-  query="gridQuery"
+  grid-controls="gridControls"
   menu-label="[% l('Buckets') %]"
   persist-key="cat.bucket.record.view">
 
index 823ef72..4c4a020 100644 (file)
@@ -4,10 +4,7 @@
   <eg-grid
     idl-class="mp"
     id-field="id"
-    query="paymentQuery"
-    sort="paymentSort"
-    grid-controls="gridControls"
-    revision="paymentRevision">
+    grid-controls="gridControls">
 
     <eg-grid-action 
       label="[% l('Full Details') %]" handler="showFullDetails"></eg-grid-action>
@@ -39,8 +36,6 @@
     <eg-grid-field name="copy_id" 
       path="xact.circulation.target_copy.id" required hidden></eg-grid-field>
 
-
-
     <!-- ... -->
 
     <eg-grid-field path="xact.id" required hidden></eg-grid-field>
index a349ec9..7c77e5c 100644 (file)
@@ -4,9 +4,7 @@
   <eg-grid
     idl-class="mbt"
     id-field="id"
-    query="xactQuery"
-    grid-controls="gridControls"
-    revision="xactRevision">
+    grid-controls="gridControls">
 
     <eg-grid-action 
       label="[% l('Add Billing') %]" handler="addBilling"></eg-grid-action>
index d65b7d3..8a2cc26 100644 (file)
@@ -39,8 +39,8 @@
   main-label="[% l('Checkouts') %]"
   items-provider="gridDataProvider"
   persist-key="circ.patron.checkout">
-  <eg-grid-field label="[% ('Barcode') %]"      path='copy_barcode' visible></eg-grid-field>
-  <eg-grid-field label="[% ('Circ ID') %]"      path='payload.circ.id' visible></eg-grid-field>
+  <eg-grid-field label="[% l('Barcode') %]"     path='copy_barcode' visible></eg-grid-field>
+  <eg-grid-field label="[% l('Circ ID') %]"     path='payload.circ.id' visible></eg-grid-field>
   <eg-grid-field label="[% l('Due Date') %]"    path='payload.circ.due_date' visible></eg-grid-field>
   <eg-grid-field label="[% l('Response') %]"    path='textcode' visible></eg-grid-field>
   <eg-grid-field label="[% l('Title') %]"       path='payload.record.title' visible></eg-grid-field>
index ef08445..e23c258 100644 (file)
@@ -3,9 +3,7 @@
 <div class="pad-vert"></div>
 <eg-grid
   idl-class="ausp"
-  query="activeQuery"
-  sort="activeSort"
-  revision="activeRevision">
+  grid-controls="activeGridControls">
 
   <eg-grid-menu-item handler="createPenalty"
     label="[% l('Apply Penalty / Message') %]"></eg-grid-menu-item>
@@ -39,9 +37,7 @@
 </div>
 <eg-grid
   idl-class="ausp"
-  query="archiveQuery"
-  sort="archiveSort"
-  revision="archiveRevision">
+  grid-controls="archiveGridControls">
 
   <eg-grid-field path="set_date" label="[% l('Applied On') %]"></eg-grid-field>
   <eg-grid-field path="standing_penalty.label"></eg-grid-field>
index 1d11369..7bc04e7 100644 (file)
   main-label="[% l('Bills') %]"
   idl-class="mb"
   id-field="id"
-  query="billQuery"
-  sort="billSort"
-  revision="billRevision"
+  grid-controls="xactGridControls"
   auto-fields="true"
   page-size="10">
 
   idl-class="mp"
   id-field="id"
   auto-fields="true"
-  query="paymentQuery"
-  sort="paymentSort"
-  revision="paymentRevision"
+  grid-controls="paymentGridControls"
   page-size="10">
   <eg-grid-action 
     label="[% l('Edit Note') %]" handler="editPaymentNotes"></eg-grid-action>
index d1a3714..de59a45 100644 (file)
@@ -403,11 +403,17 @@ function($scope,  $routeParams,  egCore , bucketSvc) {
     $scope.setTab('search');
     $scope.focusMe = true;
     var idQueryHash = {};
-    $scope.gridQuery = function() { 
+
+    function generateQuery() {
         if (bucketSvc.queryRecords.length)
             return {id : bucketSvc.queryRecords};
         else 
-            return {};
+            return null;
+    }
+
+    $scope.gridControls = {
+        setQuery : function() {return generateQuery()},
+        setSort : function() {return ['id']}
     }
 
     // add selected items directly to the pending list
@@ -432,6 +438,7 @@ function($scope,  $routeParams,  egCore , bucketSvc) {
         ).then(function(resp) {
             bucketSvc.queryRecords = 
                 resp.ids.map(function(id){return id[0]});
+            $scope.gridControls.setQuery(generateQuery());
         })['finally'](function() {
             $scope.searchInProgress = false;
         });
@@ -458,7 +465,6 @@ function($scope,  $routeParams,  bucketSvc , egGridDataProvider) {
         return provider.arrayNotifier(
             bucketSvc.pendingList, offset, count);
     }
-    provider.itemFieldValue = provider.flatItemFieldValue;
     $scope.gridDataProvider = provider;
 
     $scope.resetPendingList = function() {
@@ -484,12 +490,13 @@ function($scope,  $q , $routeParams,  bucketSvc) {
     $scope.setTab('view');
     $scope.bucketId = $routeParams.id;
 
-    // when no items are linked to a bucket, use noQuery, since the 
-    // watchers will see it's the same value (and not a new ref to 
-    // a new {} each time)
-    var noQuery = {};
-    var myQuery = {};
-    $scope.gridQuery = function() { return myQuery }
+    var query;
+    $scope.gridControls = {
+        setQuery : function(q) {
+            if (q) query = q;
+            return query;
+        }
+    };
 
     function drawBucket() {
         return bucketSvc.fetchBucket($scope.bucketId).then(
@@ -498,9 +505,9 @@ function($scope,  $q , $routeParams,  bucketSvc) {
                     function(i){return i.target_biblio_record_entry()}
                 );
                 if (ids.length) {
-                    myQuery = {id : ids};
+                    $scope.gridControls.setQuery({id : ids});
                 } else {
-                    myQuery = noQuery;
+                    $scope.gridControls.setQuery({});
                 }
             }
         );
index 9ed3ac1..a104e75 100644 (file)
@@ -130,13 +130,31 @@ function($scope , $location , egCore , egGridDataProvider , itemSvc) {
 function($scope , $q , $location , $timeout , egCore , egGridDataProvider , itemSvc) {
     $scope.context.page = 'list';
 
+    /*
     var provider = egGridDataProvider.instance();
     provider.get = function(offset, count) {
-        return provider.arrayNotifier(itemSvc.copies, offset, count);
     }
+    */
 
-    provider.itemFieldValue = provider.flatItemFieldValue;
-    $scope.gridDataProvider = provider;
+    $scope.gridDataProvider = egGridDataProvider.instance({
+        get : function(offset, count) {
+            //return provider.arrayNotifier(itemSvc.copies, offset, count);
+            return this.arrayNotifier(itemSvc.copies, offset, count);
+        }
+    });
+
+    // If a copy was just displayed in the detail view, ensure it's
+    // focused in the list view.
+    var selected = false;
+    var copyGrid = $scope.gridControls = {
+        itemRetrieved : function(item) {
+            if (selected || !itemSvc.copy) return;
+            if (itemSvc.copy.id() == item.id) {
+                copyGrid.selectItems([item.index]);
+                selected = true;
+            }
+        }
+    };
 
     $scope.$watch('barcodesFromFile', function(newVal, oldVal) {
         if (newVal && newVal != oldVal) {
@@ -152,8 +170,8 @@ function($scope , $q , $location , $timeout , egCore , egGridDataProvider , item
 
             itemSvc.fetch(barcodes).then(
                 function() {
-                    provider.increment()
-                    provider.selectOneItem(itemSvc.copies[0].index);
+                    copyGrid.refresh();
+                    copyGrid.selectItems([itemSvc.copies[0].index]);
                 }
             );
         }
@@ -164,8 +182,8 @@ function($scope , $q , $location , $timeout , egCore , egGridDataProvider , item
         $scope.context.itemNotFound = false;
         itemSvc.fetch(args.barcode).then(function(res) {
             if (res) {
-                provider.increment();
-                provider.selectOneItem(res.index);
+                copyGrid.refresh();
+                copyGrid.selectItems([res.index]);
                 $scope.args.barcode = '';
             } else {
                 $scope.context.itemNotFound = true;
@@ -174,21 +192,8 @@ function($scope , $q , $location , $timeout , egCore , egGridDataProvider , item
         })
     }
 
-    // If a copy was just displayed in the detail view, ensure it's
-    // focused in the list view.
-    var selected = false;
-    $scope.gridControls = {
-        itemRetrieved : function(item) {
-            if (selected || !itemSvc.copy) return;
-            if (itemSvc.copy.id() == item.id) {
-                provider.selectOneItem(item.index);
-                selected = true;
-            }
-        }
-    };
-
     $scope.context.toggleDisplay = function() {
-        var item = provider.getSelectedItems()[0];
+        var item = copyGrid.selectedItems()[0];
         if (item) 
             $location.path('/cat/item/' + item.id);
     }
index 4e4820f..829a4c8 100644 (file)
@@ -61,25 +61,16 @@ function($scope,  $q,  $modal,  egCore,  checkinSvc, egGridDataProvider,
     $scope.checkins = checkinSvc.checkins;
 
     var provider = egGridDataProvider.instance({});
-    provider.initialize = function() {
-        return {offset : 0};
-    }
-
     provider.get = function(offset, count) {
         return provider.arrayNotifier(
             $scope.checkins, offset, count
         );
     }
-
-    provider.itemFieldValue = function(item, column) {
-        return provider.nestedItemFieldValue(item, column);
-    };
-
     $scope.gridDataProvider = provider;
 
     function addCheckin(evt) {
         checkinSvc.checkins.push(evt);
-        provider.increment();
+        provider.refresh();
     }
 
 
index 4ae79ff..06a1889 100644 (file)
@@ -47,8 +47,6 @@ function($scope,  egCore,  egGridDataProvider , egConfirmDialog) {
     provider.get = function(offset, count) {
         return provider.arrayNotifier(checkouts, offset, count);
     }
-
-    provider.itemFieldValue = provider.nestedItemFieldValue;
     $scope.gridDataProvider = provider;
 
     // currently selected non-cat type
@@ -118,7 +116,7 @@ function($scope,  egCore,  egGridDataProvider , egConfirmDialog) {
             item.index = checkouts.length;
 
             checkouts.unshift(item);
-            provider.increment();
+            provider.refresh();
         });
     }
 
index 46080a9..28a79ac 100644 (file)
@@ -217,10 +217,6 @@ function($q , $timeout , $location , egCore,  egUser , $locale) {
                 function(user) {
                     service.current = user;
                     service.localFlesh(user);
-                    service.alert_penalties = user.standing_penalties()
-                        .filter(function(pen) { 
-                        return pen.standing_penalty().staff_alert() == 't' 
-                    });
                     return service.fetchUserStats();
                 },
                 function(err) {
@@ -357,6 +353,10 @@ function($q , $timeout , $location , egCore,  egUser , $locale) {
         return service.getUserStats(service.current.id())
         .then(function(stats) {
             service.patron_stats = stats
+            service.alert_penalties = service.current.standing_penalties()
+                .filter(function(pen) { 
+                return pen.standing_penalty().staff_alert() == 't' 
+            });
             return service.fetchGroupFines();
         });
     }
@@ -549,10 +549,6 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
         selectedItems : function() {return []}
     }
 
-    // cache of object field values; speeds up grid rendering for
-    // nested objects.  TODO: move into grid?
-    var fieldValueCache = {};
-
     if (patronSvc.lastSearch) {
         // populate the search form with our cached search info
         angular.forEach(patronSvc.lastSearch.search, function(val, key) {
@@ -561,9 +557,6 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
     }
 
     var provider = egGridDataProvider.instance({});
-    provider.initialize = function() {
-        return {offset : 0};
-    }
 
     $scope.$watch(
         function() {return $scope.gridControls.selectedItems()},
@@ -631,7 +624,6 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
             return deferred.promise;
         }
 
-        fieldValueCache = {};
         patronSvc.patrons = [];
         egCore.net.request(
             'open-ils.actor',
@@ -658,22 +650,6 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
         return deferred.promise;
     };
 
-    provider.itemFieldValue = function(item, column) {
-
-        if (fieldValueCache[item.id()]) {
-            if (fieldValueCache[item.id()][column.path] !== undefined) {
-                return fieldValueCache[item.id()][column.path];
-            }
-        } else {
-            fieldValueCache[item.id()] = {};
-        }
-
-        fieldValueCache[item.id()][column.path] =
-            provider.nestedItemFieldValue(item, column);
-
-        return fieldValueCache[item.id()][column.path];
-    };
-
     $scope.patronSearchGridProvider = provider;
 
     // typeahead doesn't filter correctly with full hash objects, so
@@ -687,18 +663,14 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
     $scope.org_units = egCore.env.aou.list.map(
         function(org) {return {shortname : org.shortname(), id : org.id() }})
 
-    // 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);
+        egCore.hatch.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;
 
+    egCore.hatch.getItem('eg.prefs.circ.patron.search.showExtras')
+    .then(function(val) {$scope.showExtras = val});
 
     // map form arguments into search params
     function compileSearch(args) {
@@ -761,7 +733,7 @@ function($scope,  $q,  $routeParams,  $timeout,  $window,  $location,  egCore,
     // refresh itself.
     $scope.search = function(args) { // args === $scope.searchArgs
         if (args && Object.keys(args).length) 
-            provider.increment(true);
+            $scope.gridControls.refresh();
     }
 
     // TODO: move this into the (forthcoming) grid row activate action
@@ -796,25 +768,34 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
     }
 
     // grid queries
+   
+    var activeGrid = $scope.activeGridControls = {
+        setSort : function() {
+            return ['set_date'];
+        },
+        setQuery : function() {
+            return {
+                usr : usr_id,
+                '-or' : [
+                    {stop_date : null},
+                    {stop_date : {'>' : 'now'}}
+                ]
+            }
+        }
+    }
 
-    $scope.activeRevision = $scope.archiveRevision = 0;
-    $scope.activeSort = $scope.archiveSort = ['set_date'];
-    $scope.activeQuery = function() {
-        return {
-            usr : usr_id,
-            '-or' : [
-                {stop_date : null},
-                {stop_date : {'>' : 'now'}}
-            ]
+    var archiveGrid = $scope.archiveGridControls = {
+        setSort : function() {
+            return ['set_date'];
+        },
+        setQuery : function() {
+            return {
+                usr : usr_id, 
+                stop_date : {'<=' : 'now'},
+                set_date : {between : date_range()}
+            };
         }
     };
-    $scope.archiveQuery = function() {
-        return {
-            usr : usr_id, 
-            stop_date : {'<=' : 'now'},
-            set_date : {between : date_range()}
-        };
-    };
 
     $scope.removePenalty = function(selected) {
         // the grid stores flattened penalties.  Fetch penalty objects first
@@ -830,7 +811,7 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
 
         // then refresh the grid
         }).then(function() {
-            $scope.activeRevision++; 
+            activeGrid.refresh();
         });
     }
 
@@ -849,8 +830,8 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
 
         // then refresh the grid
         }).then(function() {
-            $scope.activeRevision++; 
-            $scope.archiveRevision++; 
+            activeGrid.refresh();
+            archiveGrid.refresh();
         });
     }
 
@@ -893,7 +874,7 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
                 pen.staff(egCore.auth.user().id());
                 pen.set_date('now');
                 egCore.pcrud.create(pen).then(function() { 
-                    $scope.activeRevision++ 
+                    activeGrid.refresh();
                     // force a refresh of the user, since they may now
                     // have blocking penalties, etc.
                     patronSvc.setDefault(patronSvc.current.id(), null, true);
@@ -932,7 +913,7 @@ function($scope , $q , $routeParams,  egCore , $modal , patronSvc) {
                 penalty.note(args.note);
                 penalty.standing_penalty(args.penalty);
                 egCore.pcrud.update(penalty).then(function() { 
-                    $scope.activeRevision++ 
+                    activeGrid.refresh();
                     // force a refresh of the user, since they may now
                     // have blocking penalties, etc.
                     patronSvc.setDefault(patronSvc.current.id(), null, true);
@@ -980,10 +961,9 @@ function($scope,  $routeParams , $location , egCore) {
         egCore.net.request(
             'open-ils.actor',
             'open-ils.actor.verify_user_password',
-            egCore.auth.token(),
-            $scope.barcode,
-            $scope.username, 
-            hex_md5($scope.password || '')
+            egCore.auth.token(), $scope.barcode,
+            $scope.username, hex_md5($scope.password || '')
+
         ).then(function(resp) {
             $scope.focusMe = true;
             if (evt = egCore.evt.parse(resp)) {
@@ -1004,9 +984,7 @@ function($scope,  $routeParams , $location , egCore) {
         egCore.net.request(
             'open-ils.actor',
             'open-ils.actor.user.retrieve_id_by_barcode_or_username',
-            egCore.auth.token(),
-            $scope.barcode,
-            $scope.username
+            egCore.auth.token(), $scope.barcode, $scope.username
 
         ).then(function(resp) {
 
@@ -1116,21 +1094,19 @@ function($scope,  $routeParams , $q , $location , egCore ,
 
     var usr_id = $routeParams.id;
 
-    var statsCache = {};
     $scope.totals = {owed : 0, total_out : 0, overdue : 0}
 
-    $scope.gridSort = ['create_date'];
-    var initQuery;
     var grid = $scope.gridControls = {
         activateItem : function(item) {
             $location.path('/circ/patron/' + item.id + '/checkout');
         },
         itemRetrieved : function(item) {
 
-            if (statsCache[item.id]) {
-                item.stats = statsCache[item.id];
+            if (item.id == patronSvc.current.id()) {
+                item.stats = patronSvc.patron_stats;
+
             } else {
-                // user retrieved, flesh their stats
+                // flesh stats for other group members
                 patronSvc.getUserStats(item.id).then(function(stats) {
                     item.stats = statsCache[item.id] = stats;
                     $scope.totals.total_out += stats.checkouts.total_out; 
@@ -1138,12 +1114,9 @@ function($scope,  $routeParams , $q , $location , egCore ,
                 });
             }
         },
-        /*
-        setQuery : function(q) {
-            if (q) initQuery = q;
-            return initQuery;
+        setSort : function() {
+            return ['create_date'];
         }
-        */
     }
 
     $scope.initTab('other', $routeParams.id)
index 4c7676e..f6e7833 100644 (file)
@@ -128,13 +128,11 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
     $scope.annotate_payment = false;
     $scope.receipt_count = 1;
     $scope.receipt_on_pay = false;
-    $scope.gridRevision = 0;
 
     // pre-define list-returning funcs in case we access them
     // before the grid instantiates
     $scope.gridControls = {
         focusRowSelector : false,
-        selectItems : function(){},
         selectedItems : function(){return []},
         allItems : function(){return []},
         itemRetrieved : function(item) {
@@ -142,6 +140,16 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
         },
         activateItem : function(item) {
             $scope.showFullDetails([item]);
+        },
+        setQuery : function() {    
+            return {
+                usr : billSvc.userId, 
+                xact_finish : null,
+                'summary.balance_owed' : {'<>' : 0}
+            }
+        }, 
+        setSort : function() {
+            return ['xact_start']; 
         }
     }
 
@@ -199,16 +207,6 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
         return -(amount / 100);
     }
 
-    var query = {
-        usr : billSvc.userId, 
-        xact_finish : null,
-        'summary.balance_owed' : {'<>' : 0}
-    };
-
-    $scope.gridQuery = function() {return query};
-    $scope.gridSort = ['xact_start']; // default sort
-
-
     // update the item.payment_pending value each time the user
     // selects different transactions to pay against.
     $scope.$watch(
@@ -266,8 +264,9 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
 
     function refreshDisplay() {
         patronSvc.fetchUserStats();
+        billSvc.fetchSummary().then(function(s) {$scope.summary = s});
         $scope.payment_amount = 0;
-        $scope.gridRevision++; // tell the grid to refresh itself
+        $scope.gridControls.refresh();
     }
 
     // generates payments, collects user note if needed, and sends payment
@@ -284,7 +283,6 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
             }
 
             refreshDisplay();
-            billSvc.fetchSummary().then(function(s) {$scope.summary = s});
         })
     }
 
@@ -507,16 +505,16 @@ function($scope,  $q , $routeParams , egCore , egGridDataProvider , patronSvc ,
 
     $scope.initTab('bills', $routeParams.id);
     var xact_id = $routeParams.xact_id;
-    var bills = [];
-    var payments = [];
 
-    $scope.billQuery = function() {return {xact : xact_id}};
-    $scope.billSort = ['billing_ts'];
-    $scope.billRevision = 0;
+    var xactGrid = $scope.xactGridControls = {
+        setQuery : function() { return {xact : xact_id} },
+        setSort : function() { return ['billing_ts'] }
+    }
 
-    $scope.paymentQuery = function() {return {xact : xact_id}};
-    $scope.paymentSort = ['payment_ts'];
-    $scope.paymentRevision = 0;
+    var paymentGrid = $scope.paymentGridControls = {
+        setQuery : function() { return {xact : xact_id} },
+        setSort : function() { return ['payment_ts'] }
+    }
 
     // -- actions
     $scope.voidBillings = function(bill_list) {
@@ -540,7 +538,7 @@ function($scope,  $q , $routeParams , egCore , egGridDataProvider , patronSvc ,
                 $scope.xact = xact
             });
 
-            $scope.billRevision++;
+            xactGrid.refresh();
         });
     }
 
@@ -560,9 +558,9 @@ function($scope,  $q , $routeParams , egCore , egGridDataProvider , patronSvc ,
 
                     billSvc[func](value, ids).then(function() {
                         if (type == 'payment') {
-                            $scope.paymentRevision++;
+                            paymentGrid.refresh();
                         } else {
-                            $scope.billRevision++;
+                            xactGrid.refresh();
                         }
                     });
                 }
@@ -632,9 +630,20 @@ function($scope,  $q , egCore , patronSvc , billSvc , egPromptDialog , $location
         selectedItems : function(){return []},
         activateItem : function(item) {
             $scope.showFullDetails([item]);
+        },
+        setQuery : function() {
+            // open-ils.actor.user.transactions.history.have_bill_or_payment
+            return {
+                '-or' : [
+                    {'summary.balance_owed' : {'<>' : 0}},
+                    {'summary.last_payment_ts' : {'<>' : null}}
+                ],
+                xact_start : {between : $scope.date_range()},
+                usr : billSvc.userId
+            }
         }
     }
-    $scope.xactRevision = 0;
+
 
     // TODO; move me to service
     function selected_payment_info() {
@@ -657,18 +666,6 @@ function($scope,  $q , egCore , patronSvc , billSvc , egPromptDialog , $location
         return selected_payment_info().paid;
     }
 
-    $scope.xactQuery = function() {
-        // open-ils.actor.user.transactions.history.have_bill_or_payment
-        return {
-            '-or' : [
-                {'summary.balance_owed' : {'<>' : 0}},
-                {'summary.last_payment_ts' : {'<>' : null}}
-            ],
-            xact_start : {between : $scope.date_range()},
-            usr : billSvc.userId
-        }
-    }
-
     $scope.showFullDetails = function(all) {
         if (all[0]) 
             $location.path('/circ/patron/' + 
@@ -682,10 +679,12 @@ function($scope,  $q , egCore , patronSvc , billSvc , egPromptDialog , $location
             egBilling.showBillDialog({
                 xact : egCore.idl.flatToNestedHash(all[0]),
                 patron : $scope.patron()
-            }).then(function() { $scope.xactRevision++; })
+            }).then(function() { 
+                $scope.gridControls.refresh();
+                patronSvc.fetchUserStats();
+            })
         }
     }
-
 }])
 
 .controller('BillPaymentHistoryCtrl',
@@ -696,14 +695,15 @@ function($scope,  $q , egCore , patronSvc , billSvc , $location) {
         selectedItems : function(){return []},
         activateItem : function(item) {
             $scope.showFullDetails([item]);
-        }
-    }
-
-    $scope.paymentSort = [{'payment_ts' : 'DESC'}, 'id'];
-    $scope.paymentQuery = function() {
-        return {
-            'payment_ts' : {between : $scope.date_range()},
-            'xact.usr' : billSvc.userId
+        },
+        setSort : function() {
+            return [{'payment_ts' : 'DESC'}, 'id'];
+        },
+        setQuery : function() {
+            return {
+                'payment_ts' : {between : $scope.date_range()},
+                'xact.usr' : billSvc.userId
+            }
         }
     }
 
index d52b3a4..dfde72a 100644 (file)
@@ -18,17 +18,12 @@ function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc ,
     // Grid Provider -------------------
     var provider = egGridDataProvider.instance({});
     provider.get = function(offset, count) {
-        return provider.arrayNotifier(
-            $scope.checkouts, offset, count
-        );
+        return provider.arrayNotifier($scope.checkouts, offset, count);
     }
-    provider.itemFieldValue = function(item, column) {
-        return provider.nestedItemFieldValue(item, column);
-    };
 
     function addCheckout(co) {
         $scope.checkouts.push(co);
-        provider.increment();
+        provider.refresh();
     }
 
     $scope.gridDataProvider = provider;
@@ -69,7 +64,7 @@ function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc ,
             performCheckout(coArgs);
 
         } else {
-            console.log('noncat..');
+            console.debug('noncat..');
             openNoncatDialog(coArgs);
         }
 
@@ -121,7 +116,7 @@ function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc ,
             }
         }
 
-        console.log('checkout: ' + JSON.stringify(evt, null, 2));
+        console.debug('checkout: ' + JSON.stringify(evt, null, 2));
 
         switch (evt.textcode) {
             case 'SUCCESS':
index 4853472..78031e1 100644 (file)
@@ -9,7 +9,6 @@ function($scope,  $q,  $routeParams,  egCore,  egUser,  patronSvc,  egGridDataPr
     $scope.initTab('holds', $routeParams.id);
 
     var provider = egGridDataProvider.instance({});
-    provider.itemFieldValue = provider.nestedItemFieldValue;
     $scope.gridDataProvider = provider;
 
     function fetchHolds(offset, count) {
index 4ea7571..d80e022 100644 (file)
@@ -10,7 +10,6 @@ function($scope,  $q,  $routeParams,  egCore , egUser,  patronSvc , egGridDataPr
     $scope.initTab('items_out', $routeParams.id);
     
     var provider = egGridDataProvider.instance({});
-    provider.itemFieldValue = provider.nestedItemFieldValue;
     $scope.gridDataProvider = provider;
 
     function fetchCircs(offset, count) {
index dd27cc4..e7553a2 100644 (file)
@@ -107,26 +107,10 @@ angular.module('egGridMod',
                 $scope.showGridConf = false;
                 grid.totalCount = -1;
                 $scope.selected = {};
+                $scope.actions = []; // actions for selected items
+                $scope.menuItems = []; // global actions
 
-                // actions for selected items
-                $scope.actions = [];
-                grid.addAction = function(act) {
-                    $scope.actions.push(act);
-                }
-
-                // global actions
-                $scope.menuItems = [];
-                grid.addMenuItem = function(item) {
-                    $scope.menuItems.push(item);
-                    var handler = item.handler;
-                    item.handler = function() {
-                        $scope.gridMenuIsOpen = false; // close menu
-                        if (handler) {
-                            handler(item, 
-                                item.handlerData, grid.getSelectedItems());
-                        }
-                    }
-                }
+                // remove some unneeded values from the scope to reduce bloat
 
                 grid.idlClass = $scope.idlClass;
                 delete $scope.idlClass;
@@ -144,7 +128,8 @@ angular.module('egGridMod',
                     $scope.features.split(',') : [];
                 delete $scope.features;
 
-                //$scope.disableMultiSort = features.indexOf('-multisort') > -1;
+                if (!grid.indexField && grid.idlClass)
+                    grid.indexField = egCore.idl.classes[grid.idlClass].pkey;
 
                 grid.columnsProvider = egGridColumnsProvider.instance({
                     idlClass : grid.idlClass,
@@ -153,35 +138,18 @@ angular.module('egGridMod',
                     defaultToNoMultiSort : (features.indexOf('-multisort') > -1)
                 });
 
-                $scope.showAllColumns = function() {
-                    grid.columnsProvider.showAllColumns();
-                }
-
-                $scope.hideAllColumns = function() {
-                    grid.columnsProvider.hideAllColumns();
-                }
-
-                $scope.toggleColumnVisibility = function(col) {
-                    $scope.gridColumnPickerIsOpen = false;
-                    col.visible = !col.visible;
-
-                    // egGridFlatDataProvider only retrieves data to be
-                    // displayed.  When column visibility changes, it's
-                    // necessary to fetch the newly visible column data.
-                    if (grid.selfManagedData) grid.collect();
-                }
-
-                if (!grid.indexField && grid.idlClass)
-                    grid.indexField = egCore.idl.classes[grid.idlClass].pkey;
-
                 if ($scope.autoFields) {
-                    if (grid.autoLabel)
-                        $scope.mainLabel = egCore.idl.classes[grid.idlClass].label;
+                    if (grid.autoLabel) {
+                        $scope.mainLabel = 
+                            egCore.idl.classes[grid.idlClass].label;
+                    }
                     grid.columnsProvider.compileAutoColumns();
                     delete $scope.autoFields;
                 }
    
                 if (!grid.dataProvider) {
+                    // no provider, um, provided.
+                    // Use a flat data provider
 
                     grid.selfManagedData = true;
                     grid.dataProvider = egGridFlatDataProvider.instance({
@@ -192,9 +160,6 @@ angular.module('egGridMod',
                     });
                 }
 
-                grid.dataProvider.sort = $scope.sort || [];
-                delete $scope.sort;
-
                 $scope.itemFieldValue = grid.dataProvider.itemFieldValue;
                 $scope.indexValue = function(item) {
                     return grid.indexValue(item)
@@ -207,13 +172,17 @@ angular.module('egGridMod',
                     // replaces the columns array.
                     $scope.columns = grid.columnsProvider.columns;
                 });
+
+                // NOTE: grid.collect() is first called from link(), not here.
             }
 
-            // link our control functions into the gridControls scope
-            // object so the caller can access them.
+            // link our control functions into the gridControls 
+            // scope object so the caller can access them.
             grid.applyControlFunctions = function() {
 
-                var controls = $scope.gridControls;
+                // we use some of these controls internally, so sett
+                // them up even if the caller doesn't request them.
+                var controls = $scope.gridControls || {};
 
                 // link in the control functions
                 controls.selectedItems = function() {
@@ -241,26 +210,43 @@ angular.module('egGridMod',
 
                 controls.setQuery = function(query) {
                     grid.dataProvider.query = query;
-                    controls.refresh(true);
+                    controls.refresh();
                 }
 
                 // if the caller provided a functional setSort
                 // extract the value before replacing it
-                if (controls.setSort) {
-                    grid.dataProvider.sort = 
-                        controls.setSort();
-                }
+                grid.dataProvider.sort = 
+                    controls.setSort ?  controls.setSort() : [];
 
                 controls.setSort = function(sort) {
-                    controls.refresh(true);
+                    controls.refresh();
                 }
 
-                controls.refresh = function(reset) {
-                    if (reset) grid.offset = 0;
+                controls.refresh = function(noReset) {
+                    if (!noReset) grid.offset = 0;
                     grid.collect();
                 }
 
                 grid.dataProvider.refresh = controls.refresh;
+                grid.controls = controls;
+            }
+
+            // add a new (global) grid menu item
+            grid.addMenuItem = function(item) {
+                $scope.menuItems.push(item);
+                var handler = item.handler;
+                item.handler = function() {
+                    $scope.gridMenuIsOpen = false; // close menu
+                    if (handler) {
+                        handler(item, 
+                            item.handlerData, grid.getSelectedItems());
+                    }
+                }
+            }
+
+            // add a selected-items action
+            grid.addAction = function(act) {
+                $scope.actions.push(act);
             }
 
             // remove the stored column configuration preferenc, then recover 
@@ -274,6 +260,23 @@ angular.module('egGridMod',
                 });
             }
 
+            $scope.showAllColumns = function() {
+                grid.columnsProvider.showAllColumns();
+            }
+
+            $scope.hideAllColumns = function() {
+                grid.columnsProvider.hideAllColumns();
+            }
+
+            $scope.toggleColumnVisibility = function(col) {
+                $scope.gridColumnPickerIsOpen = false;
+                col.visible = !col.visible;
+
+                // egGridFlatDataProvider only retrieves data to be
+                // displayed.  When column visibility changes, it's
+                // necessary to fetch the newly visible column data.
+                if (grid.selfManagedData) grid.collect();
+            }
 
             // save the columns configuration (position, sort, width) to
             // eg.grid.<persist-key>
@@ -773,15 +776,15 @@ angular.module('egGridMod',
                 grid.collecting = true;
                 grid.dataProvider.get(grid.offset, grid.limit).then(
                 function() {
-                    if ($scope.gridControls.allItemsRetrieved)
-                        $scope.gridControls.allItemsRetrieved();
+                    if (grid.controls.allItemsRetrieved)
+                        grid.controls.allItemsRetrieved();
                 },
                 null, 
                 function(item) {
                     if (item) {
                         $scope.items.push(item)
-                        if ($scope.gridControls.itemRetrieved)
-                            $scope.gridControls.itemRetrieved(item);
+                        if (grid.controls.itemRetrieved)
+                            grid.controls.itemRetrieved(item);
                     }
                 })['finally'](function() { grid.collecting = false })
             }
@@ -1039,7 +1042,7 @@ angular.module('egGridMod',
             // definitions.  If a match is found, back out.
             if (cols.columns.filter(function(c) {
                 return (c.path == colSpec.path) })[0]) {
-                console.debug('skipping column ' + colSpec.path);
+                //console.debug('skipping column ' + colSpec.path);
                 return;
             }
 
@@ -1148,6 +1151,7 @@ angular.module('egGridMod',
             if (!args) args = {};
 
             gridData.sort = [];
+            gridData.get = args.get;
             gridData.query = args.query;
             gridData.idlClass = args.idlClass;
             gridData.columnsProvider = args.columnsProvider;
@@ -1171,19 +1175,19 @@ angular.module('egGridMod',
 
             // Calls the grid refresh function.  Once instantiated, the
             // grid will replace this function with it's own refresh()
-            gridData.refresh = function(reset) { }
-
-            // returns a promise whose notify() delivers items
-            gridData.get = function(index, count) {
-                console.error("egGridDataProvider.get() not implemented");
-            }
+            gridData.refresh = function(noReset) { }
 
-            // called when one or more items are selected in the grid
-            gridData.select = function(items) {
+            if (!gridData.get) {
+                // returns a promise whose notify() delivers items
+                gridData.get = function(index, count) {
+                    console.error("egGridDataProvider.get() not implemented");
+                }
             }
 
             // attempts a flat field lookup first.  If the column is not
             // found on the top-level object, attempts a nested lookup
+            // TODO: consider a caching layer to speed up template 
+            // rendering, particularly for nested objects?
             gridData.itemFieldValue = function(item, column) {
                 if (column.name in item) {
                     if (typeof item[column.name] == 'function') {
@@ -1196,7 +1200,10 @@ angular.module('egGridMod',
                 }
             }
 
+            // TODO: deprecate me
             gridData.flatItemFieldValue = function(item, column) {
+                console.warn('gridData.flatItemFieldValue deprecated; '
+                    + 'leave provider.itemFieldValue unset');
                 return item[column.name];
             }