From 368872fb4c5be31066b53d21724b93d7bc392628 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Thu, 15 May 2014 13:29:07 -0400 Subject: [PATCH] item status UI continued Signed-off-by: Bill Erickson --- Open-ILS/src/templates/staff/cat/item/index.tt2 | 17 +- Open-ILS/src/templates/staff/cat/item/t_list.tt2 | 3 +- Open-ILS/src/templates/staff/share/t_autogrid.tt2 | 9 +- Open-ILS/web/js/ui/default/staff/cat/item/app.js | 213 ++++++++++++++-------- Open-ILS/web/js/ui/default/staff/services/grid.js | 20 +- 5 files changed, 182 insertions(+), 80 deletions(-) diff --git a/Open-ILS/src/templates/staff/cat/item/index.tt2 b/Open-ILS/src/templates/staff/cat/item/index.tt2 index 7a774df3dc..aee8eaf2b3 100644 --- a/Open-ILS/src/templates/staff/cat/item/index.tt2 +++ b/Open-ILS/src/templates/staff/cat/item/index.tt2 @@ -24,14 +24,25 @@

[% l('Scan Item') %]

-
+
- + + + + + + + + +
diff --git a/Open-ILS/src/templates/staff/cat/item/t_list.tt2 b/Open-ILS/src/templates/staff/cat/item/t_list.tt2 index 316a9f022a..882365943f 100644 --- a/Open-ILS/src/templates/staff/cat/item/t_list.tt2 +++ b/Open-ILS/src/templates/staff/cat/item/t_list.tt2 @@ -1,10 +1,11 @@ + diff --git a/Open-ILS/src/templates/staff/share/t_autogrid.tt2 b/Open-ILS/src/templates/staff/share/t_autogrid.tt2 index ccfc46ee68..27439e9e34 100644 --- a/Open-ILS/src/templates/staff/share/t_autogrid.tt2 +++ b/Open-ILS/src/templates/staff/share/t_autogrid.tt2 @@ -17,11 +17,18 @@ + + +
diff --git a/Open-ILS/web/js/ui/default/staff/cat/item/app.js b/Open-ILS/web/js/ui/default/staff/cat/item/app.js index c36e6215d9..1fcdf169bd 100644 --- a/Open-ILS/web/js/ui/default/staff/cat/item/app.js +++ b/Open-ILS/web/js/ui/default/staff/cat/item/app.js @@ -28,77 +28,119 @@ angular.module('egItemStatus', $routeProvider.otherwise({redirectTo : '/cat/item/search'}); }) +.factory('itemSvc', + ['egCore', +function(egCore) { + + var service = { + copies : [], // copy barcode search results + index : 0 // search grid index + }; + + service.flesh = { + flesh : 3, + flesh_fields : { + acp : ['call_number','location','status','location'], + acn : ['record'], + bre : ['simple_record','creator','editor'] + }, + select : { + // avoid fleshing MARC on the bre + // note: don't add simple_record.. not sure why + bre : ['id','tcn_value','creator','editor'], + } + } + + service.fetch = function(barcode, id) { + var promise; + + if (barcode) { + promise = egCore.pcrud.search('acp', + {barcode : barcode, deleted : 'f'}, service.flesh); + } else { + promise = egCore.pcrud.retrieve('acp', id, service.flesh); + } + + return promise.then(function(copy) { + if (!copy) return null; + + var flatCopy = egCore.idl.toHash(copy, true); + flatCopy.index = service.index++; + service.copies.unshift(flatCopy); + + return { + copy : copy, + index : flatCopy.index + }; + }); + } + + return service; +}]) + /** * Search bar along the top of the page. * Parent scope for list and detail views */ .controller('SearchCtrl', - ['$scope','$location','egCore','egGridDataProvider', -function($scope , $location , egCore , egGridDataProvider) { - + ['$scope','$location','egCore','egGridDataProvider','itemSvc', +function($scope , $location , egCore , egGridDataProvider , itemSvc) { $scope.focusBarcode = true; - var copies = []; - var provider = egGridDataProvider.instance({}); + // sub-scopes (search / detail-view) apply their version + // of retrieval function to $scope.context.search + // and display toggling via $scope.context.toggleDisplay + $scope.context = {}; + + $scope.toggleView = function($event) { + $scope.context.toggleDisplay(); + $event.preventDefault(); // avoid form submission + } + + $scope.args = {}; +}]) + +/** + * List view - grid stuff + */ +.controller('ListCtrl', + ['$scope','$location','$timeout','egCore','egGridDataProvider','itemSvc', +function($scope , $location , $timeout , egCore , egGridDataProvider , itemSvc) { + $scope.context.page = 'list'; + + var provider = egGridDataProvider.instance(); provider.get = function(offset, count) { - return provider.arrayNotifier(copies, offset, count); + return provider.arrayNotifier(itemSvc.copies, offset, count); } + provider.itemFieldValue = provider.flatItemFieldValue; $scope.gridDataProvider = provider; - $scope.searchCopy = function(args) { - $scope.fetchCopy(args.barcode) - .then(function(copy) { - if (copy) { - copies.unshift(egCore.idl.toHash(copy, true)); + $scope.context.search = function(args) { + itemSvc.fetch(args.barcode).then(function(res) { + if (res) { provider.increment(); - } else { - $scope.copyNotFound = true; + provider.selectOneItem(res.index); } - }); + }) } - $scope.fetchCopy(barcode, id) { - var flesh = { - flesh : 3, - flesh_fields : { - acp : ['call_number','location','status','location'], - acn : ['record'], - bre : ['simple_record','creator','editor'] - }, - select : { - // avoid fleshing MARC on the bre - // note: don't add simple_record.. not sure why - bre : ['id','tcn_value','creator','editor'], - } - }; - - var promise; - - if (barcode) { - promise = egCore.pcrud.search('acp', - {barcode : barcode, deleted : 'f'}, flesh); - } else { - promise = egCore.pcrud.retrieve('acp', id, flesh); - } - - promise.then(function(copy) { - if (!copy) { - $scope.copyNotFound = true; - return; - } - return egCore.idl.toHash(copy, true) + if (itemSvc.copy) { + // If a copy was just displayed in the detail view, ensure it's + // focused in the list view. However, give the grid a chance to + // instantiate before attempting to select any items. + $timeout(function() { + var flatCopy = itemSvc.copies.filter( + function(c) { return c.id == itemSvc.copy.id() })[0]; + provider.selectOneItem(flatCopy.index); }); } -}]) -/** - * List view - grid stuff - */ -.controller('ListCtrl', - ['$scope','$location','egCore', -function($scope , $location , egCore) { - // grid stuff + $scope.context.toggleDisplay = function() { + var item = provider.getSelectedItems()[0]; + if (item) + $location.path('/cat/item/view/' + item.id + '/summary'); + } }]) @@ -106,20 +148,22 @@ function($scope , $location , egCore) { * Detail view -- shows one copy */ .controller('ViewCtrl', - ['$scope','$location','$routeParams','egCore', -function($scope , $location , $routeParams , egCore) { + ['$scope','$location','$routeParams','egCore','itemSvc', +function($scope , $location , $routeParams , egCore , itemSvc) { var copyId = $routeParams.id; $scope.tab = $routeParams.tab; + $scope.context.page = 'detail'; - // TODO: cache data per copy - - function loadCopy() { - $scope.fetchCopy(null, copyId) - - }).then(function(copy) { - if (!copy) return; + function loadCopy(barcode) { + delete $scope.copy; + delete itemSvc.copy; - // TODO: FLATTEN EVERYTHING + return itemSvc.fetch(barcode, copyId).then(function(res) { + if (!res) return; + var copy = res.copy; + copyId = copy.id(); + $scope.args.barcode = copy.barcode(); + itemSvc.copy = copy; // locally flesh org units copy.circ_lib(egCore.org.get(copy.circ_lib())); @@ -140,7 +184,9 @@ function($scope , $location , $routeParams , egCore) { } function loadCurrentCirc() { - + delete $scope.circ; + delete $scope.circ_summary; + egCore.pcrud.search('circ', {target_copy : copyId}, { flesh : 1, @@ -176,12 +222,16 @@ function($scope , $location , $routeParams , egCore) { function loadCircCounts() { + delete $scope.circ_counts; + $scope.total_circs = 0; + $scope.total_circs_this_year = 0; + $scope.total_circs_prev_year = 0; + egCore.pcrud.search('circbyyr', {copy : copyId}, null, {atomic : true}) .then(function(counts) { $scope.circ_counts = counts; - $scope.total_circs = 0; angular.forEach(counts, function(count) { $scope.total_circs += Number(count.count()); @@ -207,20 +257,35 @@ function($scope , $location , $routeParams , egCore) { function loadPrevCirc() { } - loadCopy(); - switch($scope.tab) { - case 'summary': - loadCurrentCirc(); - loadCircCounts(); - break; + // we don't need all data on all tabs, so fetch what's needed when needed. + function loadTabData() { + switch($scope.tab) { + case 'summary': + loadCurrentCirc(); + loadCircCounts(); + break; + + case 'circs': + loadCurrentCirc(); + loadPrevCirc(); + break; + } + } - case 'circs': - loadCurrentCirc(); - loadPrevCirc(); - break; + // handle the barcode scan box, which will replace our current copy + $scope.context.search = function(args) { + // when searching by barcode, we have to wait for the + // copy to arrive (to collect the copyID) before + // fetching the remaining tab data. + loadCopy(args.barcode).then(loadTabData); + } + $scope.context.toggleDisplay = function() { + $location.path('/cat/item/search'); } + loadCopy(); + loadTabData(); }]) diff --git a/Open-ILS/web/js/ui/default/staff/services/grid.js b/Open-ILS/web/js/ui/default/staff/services/grid.js index e1cfd2be7f..1c870f0cc1 100644 --- a/Open-ILS/web/js/ui/default/staff/services/grid.js +++ b/Open-ILS/web/js/ui/default/staff/services/grid.js @@ -108,6 +108,13 @@ angular.module('egGridMod', $scope.menuItems = []; grid.addMenuItem = function(item) { $scope.menuItems.push(item); + var handler = item.handler; + if (handler) { + item.handler = function() { + handler(item, item.handlerData, + grid.getSelectedItems()); + } + } } // items needed only by the grid; remove from scope @@ -177,6 +184,14 @@ angular.module('egGridMod', if (reset) grid.offset = 0; grid.collect(); } + + grid.dataProvider.getSelectedItems = function() { + return grid.getSelectedItems(); + } + + grid.dataProvider.selectOneItem = function(index) { + return grid.selectOneItem(index); + } $scope.itemFieldValue = grid.dataProvider.itemFieldValue; $scope.indexValue = function(item) { @@ -908,6 +923,7 @@ angular.module('egGridMod', function GridDataProvider(args) { var gridData = this; + if (!args) args = {}; gridData.sort = []; gridData.query = args.query; @@ -939,7 +955,9 @@ angular.module('egGridMod', // redraw itself. If reset is true, it resets the grid paging // to page 0. gridData.increment = function(reset) { - gridData.load(reset); + // if called before the grid is instantiated, + // load() may not yet be defined. + if (gridData.load) gridData.load(reset); } // returns a promise whose notify() delivers items -- 2.11.0