From 00ae52241e7324714e6d0a9e08de8e209eaefbd4 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Mon, 7 Apr 2014 17:07:06 -0400 Subject: [PATCH] web staff : patron search, grid integration experimenting Signed-off-by: Bill Erickson --- .../src/templates/staff/circ/patron/t_search.tt2 | 12 -- .../staff/circ/patron/t_search_results.tt2 | 44 ++--- .../web/js/ui/default/staff/circ/patron/app.js | 177 +++++++++++++++------ 3 files changed, 148 insertions(+), 85 deletions(-) diff --git a/Open-ILS/src/templates/staff/circ/patron/t_search.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_search.tt2 index 02d3a434f3..f6dcb0cfb4 100644 --- a/Open-ILS/src/templates/staff/circ/patron/t_search.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/t_search.tt2 @@ -137,18 +137,6 @@
- [% INCLUDE 'staff/circ/patron/t_search_results.tt2' %]
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_search_results.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_search_results.tt2 index 1c5bf86533..312055ca45 100644 --- a/Open-ILS/src/templates/staff/circ/patron/t_search_results.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/t_search_results.tt2 @@ -1,28 +1,30 @@ - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/app.js b/Open-ILS/web/js/ui/default/staff/circ/patron/app.js index 00ff7e99f7..3d82f6dea4 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/app.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/app.js @@ -12,7 +12,7 @@ angular.module('egPatronApp', ['ngRoute', 'ui.bootstrap', .config(function($routeProvider, $locationProvider, $compileProvider) { $locationProvider.html5Mode(true); - $compileProvider.aHrefSanitizationWhitelist(/^\s*(blob):/); // grid export + $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|blob):/); // grid export // data loaded at startup which only requires an authtoken goes // here. this allows the requests to be run in parallel instead of @@ -115,7 +115,7 @@ function($q, egList, egNet, egAuth, egUser, egEnv, egOrg, egList) { checkout_overrides : {}, // keep a cache of the patron search results - patrons : egList.create({indexFieldAsFunction : true}), // patron.id() + patrons : [], checkouts : egList.create(), items_out : egList.create({indexFieldAsFunction : true}), // circ.id() holds : egList.create(), @@ -238,16 +238,82 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, $scope.initTab('search'); $scope.focusMe = true; - $scope.patrons = patronSvc.patrons; + $scope.args = $location.search(); + + console.log('PatronSearchCtrl'); // our data provider is a modified flat data provider var provider = egGridFlatDataProvider.instance({}); - provider.get = function(index, count, onitem) { - angular.forEach( - $scope.patrons.items.slice(index, index + count), - function(item) { onitem(item) } + provider.select = function(items) { + if (items[0]) { + var user = items[0]; + patronSvc.setDefault(null, user); + } + } + + provider.get = function(offset, count, onitem) { + console.log('get ' + $location.search() + ' : ' + provider._revision); + var deferred = $q.defer(); + + /* + if (args.id) { + retrieveUsers([args.id]); + egUser.get(id).then(function(user) { + patronSvc.localFlesh(user); + $scope.patrons.items[idx] = user; + }); + + } else { + sendSearch(args); + } + */ + + var search = compileSearch($location.search()); + + /* + if (Object.keys(search).length == 0 && + offset == patronSvc.cachedSearchOffset && + patronSvc.patrons.length) { + // accessing the page without a cached search + // see if we have a cached result set + angular.forEach(patronSvc.patrons, function(p) { onitem(p) }); + return; + } + */ + + //patronSvc.cachedSearchOffset = offset; + patronSvc.patrons = []; + + var home_ou = search.home_ou; + delete search.home_ou; + var inactive = search.inactive; + delete search.inactive; + + console.debug('patron search ' + js2JSON(search)); + egNet.request( + 'open-ils.actor', + 'open-ils.actor.patron.search.advanced.fleshed', + egAuth.token(), + search, + count, + compileSort(), + inactive, + home_ou, + egUser.defaultFleshFields, + offset + + ).then( + function() { deferred.resolve() }, + null, // onerror + function(user) { + patronSvc.localFlesh(user); // inline + deferred.notify(user); + } ); + + return deferred.promise; }; + provider.itemFieldValue = function(item, column) { return provider.nestedItemFieldValue(item, column); }; @@ -264,18 +330,6 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, $scope.org_units = egEnv.aou.list.map( function(org) {return {shortname : org.shortname(), id : org.id() }}) - // TODO: experiment - // if this is useful, it should be moved into a service. - $scope.tips = { - dismiss : function(tip) { - $window.localStorage.setItem('eg.tips.' + tip, 1); - }, - dismissed : function(tip) { - return $window.localStorage.getItem('eg.tips.' + tip); - } - // TODO: function to reset all tips - }; - // TODO: // another experiment -- user prefs in localStorage -- this should // be a service, which can also check (certain) user/org settings @@ -288,15 +342,17 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, $scope.showExtras = JSON.parse($window.localStorage.getItem( 'eg.prefs.circ.patron.search.showExtras')) || false; + // map form arguments into search params function compileSearch(args) { var search = {}; angular.forEach(args, function(val, key) { if (!val) return; if (key == 'profile') { - search.profile = {value : args.profile.id, group : 0}; + //search.profile = {value : args.profile.id, group : 0}; + search.profile = {value : search.profile, 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 { @@ -316,37 +372,37 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, return search; } - // send compiled search; get user IDs - /* - function __sendSearch(args) { - search = compileSearch(args); - - var home_ou = search.home_ou; - delete search.home_ou; - var inactive = search.inactive; - delete search.inactive; + function compileSort() { - console.debug('patron search ' + js2JSON(search)); - egNet.request( - 'open-ils.actor', - 'open-ils.actor.patron.search.advanced', - egAuth.token(), search, 100, - [ // sort + if (!$scope.patronSearchGridProvider.sort.length) { + return [ // default "family_name ASC", "first_given_name ASC", "second_given_name ASC", "dob DESC" - ], - inactive, - home_ou + ]; + } - ).then(function(ids) { - retrieveUsers(ids); - }); - }; - */ + var sort = []; + angular.forEach( + $scope.patronSearchGridProvider.sort, + function(sortdef) { + if (angular.isObject(sortdef)) { + var name = Object.keys(sortdef)[0]; + var dir = sortdef[name]; + sort.push(name + ' ' + dir); + } else { + sort.push(sortdef); + } + } + ); + + console.log('sort = ' + js2JSON(sort)); + return sort; + } // alt form which receives fleshed user objects + /* function sendSearch(args) { search = compileSearch(args); @@ -359,13 +415,10 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, egNet.request( 'open-ils.actor', 'open-ils.actor.patron.search.advanced.fleshed', - egAuth.token(), search, 50 /* limit */, - [ /* sort */ - "family_name ASC", - "first_given_name ASC", - "second_given_name ASC", - "dob DESC" - ], + egAuth.token(), + search, + 50 // + compileSort(), inactive, home_ou, egUser.defaultFleshFields @@ -376,9 +429,10 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, $scope.patronSearchGridProvider.increment(); }); }; - + */ // fetch users by id and add them to the patrons list + /* function retrieveUsers(ids) { angular.forEach(ids, function(id, idx) { // capture idx to maintain search results order @@ -388,20 +442,33 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, }); }); } + */ // collect form args fire patron search $scope.search = function(args) { if (args && Object.keys(args).length) { + //$scope.searchArgs = args; + //$scope.patronSearchGridProvider.increment(); + + if (args.profile) args.profile = args.profile.id; + if (args.home_ou) args.home_ou = args.home_ou.id; + + $location.search(args); + + /* + $scope. $scope.patrons.reset(); if (args.id) { retrieveUsers([args.id]); } else { sendSearch(args); } + */ } } // manage table row selection + /* $scope.onPatronClick = function($event, user) { $scope.lastSelected = user; @@ -425,6 +492,7 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, patronSvc.setDefault(null, user); } } + */ $scope.onPatronDblClick = function($event, user) { $location.path('/circ/patron/' + user.id() + '/checkout'); @@ -437,6 +505,7 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, // http://stackoverflow.com/questions/16749907/window-open-behaviour-in-chrome-tabs-windows // for now, skip this feature and support control-click to open // multiple patrons instead. + /* $scope.openSelectedPatrons = function() { angular.forEach( $scope.patrons.selectedItems(), @@ -448,6 +517,7 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, } ); } + */ // handled up/down arrow events while the patrons results table is focused. // disabled for now, since there are some UI issues to work out first: @@ -459,6 +529,8 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, // hover in its original position, making the hovered row appear to be // selected (style-wise) even when it's not. Disabling table-hover // CSS works, but table-hover is useful, so... + + /* TODO: MOVE ME INTO GRID.js $scope.navigateResults = function($event) { // we can't select the next/previous user if we don't know // which user was selected last. this should never happen, though. @@ -485,6 +557,7 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egEnv, if (user) $scope.onPatronClick($event, user); } + */ }]) -- 2.11.0