webstaff: Filter by serial item status, and page through items server-side
authorMike Rylander <mrylander@gmail.com>
Thu, 18 May 2017 16:01:18 +0000 (12:01 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Tue, 30 May 2017 16:06:46 +0000 (12:06 -0400)
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Open-ILS/src/templates/staff/serials/index.tt2
Open-ILS/src/templates/staff/serials/t_view_items_grid.tt2
Open-ILS/web/js/ui/default/staff/serials/directives/view-items-grid.js
Open-ILS/web/js/ui/default/staff/serials/services/core.js

index efa0b0a..d21f983 100644 (file)
@@ -29,6 +29,16 @@ angular.module('egCoreMod').run(['egStrings', function(s) {
     s.CONFIRM_DELETE_ITEMS = "[% l('Delete selected items?') %]";
     s.CONFIRM_DELETE_ITEMS_MESSAGE = "[% l('Will delete {{items}} items') %]";
 
+    s.SERIALS_ITEM_STATUS = {};
+    s.SERIALS_ITEM_STATUS.Expected = "[% l('Expected') %]";
+    s.SERIALS_ITEM_STATUS.Received = "[% l('Received') %]";
+    s.SERIALS_ITEM_STATUS.Claimed = "[% l('Claimed') %]";
+    s.SERIALS_ITEM_STATUS.Bindery = "[% l('Bindery') %]";
+    s.SERIALS_ITEM_STATUS.Bound = "[% l('Bound') %]";
+    s.SERIALS_ITEM_STATUS.Discarded = "[% l('Discarded') %]";
+    s.SERIALS_ITEM_STATUS['Not Held'] = "[% l('Not Held' ) %]";
+    s.SERIALS_ITEM_STATUS['Not Published'] = "[% l('Not Published') %]";
+
 }]);
 </script>
 [% END %]
index 22afd4a..23676dc 100644 (file)
@@ -4,9 +4,31 @@
     features="-display,-sort,-multisort"
     items-provider="itemGridProvider"
     grid-controls="itemGridControls"
+    menu-label="[% l('Filter items') %]"
     persist-key="serials.view_item_grid">
 
-    <eg-grid-menu-item handler="add_issuances" standalone="true" label="[% l('Predict New Issues') %]"></eg-grid-menu-item>
+    <eg-grid-menu-item handler="filter_items_all"
+      label="[% l('All') %]"></eg-grid-menu-item>
+
+    <eg-grid-menu-item handler="filter_items_have"
+      label="[% l('Held') %]"></eg-grid-menu-item>
+
+    <eg-grid-menu-item handler="filter_items_dont_have"
+      label="[% l('Not Held') %]"></eg-grid-menu-item>
+
+    <eg-grid-menu-item divider="true"></eg-grid-menu-item>
+
+    <eg-grid-menu-item ng-repeat="status in svc.item_status_i18n"
+      label="[% l('Status:') %] {{status.label}}" handler-data="status"
+      handler="filter_items_by_status"></eg-grid-menu-item>
+
+
+    <eg-grid-menu-item handler="receive_next" standalone="true"
+        label="[% l('Receive Next') %]"></eg-grid-menu-item>
+
+    <eg-grid-menu-item handler="add_issuances" standalone="true"
+        label="[% l('Predict New Issues') %]"></eg-grid-menu-item>
+
 
     <eg-grid-action handler="following_issuance" disabled="need_one_selected"
       label="[% l('Add following issue') %]"></eg-grid-action>
index f48cdb2..c584bf8 100644 (file)
@@ -15,14 +15,21 @@ angular.module('egSerialsAppDep')
 function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
          $uibModal , ngToast , egConfirmDialog) {
 
-    $scope.svc = egSerialsCoreSvc; // just for debugging
+    $scope.svc = egSerialsCoreSvc;
 
-    function reload(ssubId) {
-        return egSerialsCoreSvc.fetchItemsForSub(ssubId).then(function(list) {
+    var _paging_filter;
+    function reload(ssubId,filter) {
+        _paging_filter = filter;
+        return egSerialsCoreSvc.fetchItemsForSub(ssubId,filter).then(function() {
             $scope.itemGridProvider.refresh();
         });
     }
 
+    $scope.filter_items_all = function () { return reload($scope.ssubId) }
+    $scope.filter_items_have = function () { return reload($scope.ssubId,{status:['Received','Bindery','Bound']}) }
+    $scope.filter_items_dont_have = function () { return reload($scope.ssubId,{'-not':{status:['Received','Bindery','Bound']}}) }
+    $scope.filter_items_by_status = function (item,status) { return reload($scope.ssubId,{status:status.name}) }
+
     $scope.$watch('ssubId', function(newVal, oldVal) {
         if (newVal && newVal != oldVal) return reload(newVal);
     });
@@ -33,7 +40,14 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
 
     $scope.itemGridProvider = egGridDataProvider.instance({
         get : function(offset, count) {
-            return this.arrayNotifier(egSerialsCoreSvc.itemList, offset, count);
+            var self = this;
+            if (egSerialsCoreSvc.itemList.length >= offset + count) { // if there's anything on the requested page, notify
+                return self.arrayNotifier(egSerialsCoreSvc.itemList, offset, count);
+            } else { // else try to fetch another page
+                return egSerialsCoreSvc.fetchItemsForSubPaged($scope.ssubId, _paging_filter, offset, count).then(function() {
+                    return self.arrayNotifier(egSerialsCoreSvc.itemList, offset, count);
+                });
+            }
         }
     });
 
@@ -63,7 +77,7 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
                     ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                 } else {
                     ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
-                    return reload($scope.ssubId);
+                    return reload($scope.ssubId,_paging_filter);
                 }
             });
         });
@@ -128,7 +142,7 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
                         ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                     } else {
                         ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
-                        return reload($scope.ssubId);
+                        return reload($scope.ssubId,_paging_filter);
                     }
                 },
                 function(resp) {
@@ -143,7 +157,6 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
             title : egCore.strings.SERIALS_ISSUANCE_ADD,
             prev_iss : egCore.idl.fromHash('siss',items[0].issuance)
         }).then(function(hc) {
-            console.log(hc)
             return egCore.net.request(
                 'open-ils.serial',
                 'open-ils.serial.make_predictions',
@@ -159,7 +172,7 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
                         ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                     } else {
                         ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
-                        return reload($scope.ssubId);
+                        return reload($scope.ssubId,_paging_filter);
                     }
                 },
                 function(resp) {
@@ -179,7 +192,6 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
             request_count : true,
             prev_iss : lastItem
         }).then(function(hc) {
-            console.log(hc)
 
             var base_iss;
             if (!lastItem) {
@@ -212,7 +224,7 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
                         ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
                     } else {
                         ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
-                        return reload($scope.ssubId);
+                        return reload($scope.ssubId,_paging_filter);
                     }
                 },
                 function(resp) {
@@ -228,14 +240,6 @@ function($scope , $q , egSerialsCoreSvc , egCore , egGridDataProvider ,
         return true;
     };
 
-    if (!egSerialsCoreSvc.subTree.length) {
-        egSerialsCoreSvc.fetch($scope.bibId).then(function() {
-            return reload($scope.ssubId);
-        });
-    } else if ($scope.ssubId) {
-        reload($scope.ssubId);
-    }
-
 }]
 
     }
index 2669501..ca36f81 100644 (file)
@@ -56,9 +56,27 @@ function(egCore , orderByFilter , $q , $filter , $uibModal) {
             week  : function(d) { return $filter('date')(d, 'ww') },
             day   : function(d) { return ('00'+d.getDate()).slice(-2) },
             hour  : function(d) { return ('00'+d.getHours()).slice(-2) }
-        }
+        },
+        item_status_list : [
+            'Expected',
+            'Received',
+            'Claimed',
+            'Bindery',
+            'Bound',
+            'Discarded',
+            'Not Held',
+            'Not Published'
+        ],
+        item_status_i18n : []
     };
 
+    angular.forEach(service.item_status_list, function(status) {
+        service.item_status_i18n.push({
+            name  : status,
+            label : egCore.strings.SERIALS_ITEM_STATUS[status]
+        });
+    });
+
     function _loose_season(D) {
         var m = D.getMonth() + 1;
         var d = D.getDate();
@@ -104,9 +122,21 @@ function(egCore , orderByFilter , $q , $filter , $uibModal) {
             update_flat_sdist_sstr_list();
         });
     }
+
+    service.fetchItemsForSubPaged = function(subId,filter,offset,limit) {
+        return service.fetchItemsForSub(
+            subId,
+            filter,
+            { limit : limit, offset : offset, paging : true }
+        );
+    }
+
     // Creates an inverted tree from item to sub
-    service.fetchItemsForSub = function(subId) {
+    service.fetchItemsForSub = function(subId,filter,options) {
+        var deferred = $q.defer(); // side-effects only, otherwise the grid is wonky
+
+        if (!filter) filter = {};
+        if (!options) options = { limit : 100 }; // only used during full refresh
 
         if (!subId && service.subId) subId = service.subId;
         if (!subId) return $q.reject('fetchItemsForSub: no subscription id');
@@ -124,19 +154,30 @@ function(egCore , orderByFilter , $q , $filter , $uibModal) {
             );
         });
 
-        return egCore.pcrud.search(
-            'sitem',
-            { stream : streams },
-            { 
-                flesh : 1,
-                flesh_fields : {
-                    sitem : ['issuance','editor','creator','unit','url']
-                }
-            },
+        angular.extend(filter, {stream:streams});
+        angular.extend(options, { 
+            order_by : [{class:'sitem',field:'date_expected'}], // best aprox of pub date
+            flesh : 1,
+            flesh_fields : {
+                sitem : ['issuance','editor','creator','unit','url']
+            }
+        });
+
+        egCore.pcrud.search(
+            'sitem', filter, options,
             { atomic : true }
         ).then(function(list) {
             service.subId = subId;
-            service.itemTree = list;
+            if (!options.paging) { // not paged
+                service.itemTree = list;
+            } else { // paged
+                angular.forEach(list, function (item) {
+                    var exists = service.itemTree.filter(function (i) {
+                        return i.id() == item.id()
+                    }).length;
+                    if (!exists) service.itemTree.push(item);
+                });
+            }
 
             // map items by stream for faster lookup
             var tmp = {};
@@ -159,18 +200,18 @@ function(egCore , orderByFilter , $q , $filter , $uibModal) {
                 });
             });
 
-            var hashList = egCore.idl.toHash(list);
+            var hashList = egCore.idl.toHash(service.itemTree);
             angular.forEach(hashList, function (item) {
                 item['issuance.date_published'] = item.issuance.date_published;
+                item['stream.distribution.holding_lib.name'] = item.stream.distribution.holding_lib.name;
             });
 
             // ... then sort it
-            service.itemList.length = 0;
-            angular.extend(service.itemList,
-                orderByFilter(hashList, ['"issuance.date_published"', '"id"'])
-            );
-            return $q.when(list);
+            service.itemList = orderByFilter(hashList, ['"issuance.date_published"', '"stream.distribution.holding_lib.name"', '"id"']);
+            deferred.resolve();
         });
+
+        return deferred.promise;
     }
 
     service.prep_new_holding_code = function (args) {