From 3876d6ad634f8983a9e836953c175228cd660386 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Sat, 12 Aug 2017 11:52:40 -0400 Subject: [PATCH] LP#1709521 Webstaff show recent patrons Adds a new library setting 'ui.staff.max_recent_patrons' which specifices the number of recently accessed patrons staff may quickly refetch from the browser client interface. If no value is set, it defaults to 1 for backwards compatibility. If the value is 0 or less, no recent patrons may be retrieved and the 'Retrieve Last Patron' action is hidden. If the value is > 1 a new 'Retrieve Recent Patrons' menu item appears. When clicked, the list of recent patrons is displayed in the patron search interface, most recently accessed patrons sorted to the top. For privacy, the recent patrons list expires from the browser when the authenticion token expires. Signed-off-by: Bill Erickson --- Open-ILS/src/sql/Pg/950.data.seed-values.sql | 23 ++++++ .../sql/Pg/upgrade/XXXX.data.recent-patrons.sql | 26 +++++++ Open-ILS/src/templates/staff/navbar.tt2 | 9 ++- .../web/js/ui/default/staff/circ/patron/app.js | 5 +- .../web/js/ui/default/staff/services/navbar.js | 7 ++ .../js/ui/default/staff/services/patron_search.js | 81 ++++++++++++++++++++-- .../web/js/ui/default/staff/services/startup.js | 9 ++- 7 files changed, 151 insertions(+), 9 deletions(-) create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.data.recent-patrons.sql diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index e95d94caea..4ffb86b204 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -17125,3 +17125,26 @@ INSERT into config.org_unit_setting_type 'Define the time zone in which a library physically resides', 'coust', 'description'), 'string'); + +INSERT INTO config.org_unit_setting_type + (name, label, description, grp, datatype) +VALUES ( + 'ui.staff.max_recent_patrons', + oils_i18n_gettext( + 'ui.staff.max_recent_patrons', + 'Number of Retrievable Recent Patrons', + 'coust', + 'label' + ), + oils_i18n_gettext( + 'ui.staff.max_recent_patrons', + 'Number of most recently accessed patrons that can be re-retrieved ' || + 'in the staff client. A value of 0 or less disables the feature', + 'coust', + 'description' + ), + 'circ', + 'integer' +); + + diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.recent-patrons.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.recent-patrons.sql new file mode 100644 index 0000000000..3cf897d60b --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.recent-patrons.sql @@ -0,0 +1,26 @@ +BEGIN; + +-- SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version); + +INSERT INTO config.org_unit_setting_type + (name, label, description, grp, datatype) +VALUES ( + 'ui.staff.max_recent_patrons', + oils_i18n_gettext( + 'ui.staff.max_recent_patrons', + 'Number of Retrievable Recent Patrons', + 'coust', + 'label' + ), + oils_i18n_gettext( + 'ui.staff.max_recent_patrons', + 'Number of most recently accessed patrons that can be re-retrieved ' || + 'in the staff client. A value of 0 or less disables the feature', + 'coust', + 'description' + ), + 'circ', + 'integer' +); + +COMMIT; diff --git a/Open-ILS/src/templates/staff/navbar.tt2 b/Open-ILS/src/templates/staff/navbar.tt2 index ba99321dd1..c42c8cfd65 100644 --- a/Open-ILS/src/templates/staff/navbar.tt2 +++ b/Open-ILS/src/templates/staff/navbar.tt2 @@ -114,7 +114,7 @@ [% l('Register Patron') %] -
  • +
  • @@ -122,6 +122,13 @@ [% l('Retrieve Last Patron') %]
  • +
  • + + + [% l('Retrieve Recent Patrons') %] + +
  • 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 cd8a36e7aa..0ee219c7f4 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 @@ -1113,8 +1113,9 @@ function($scope, $routeParams , $location , egCore , patronSvc) { ['$scope','$location','egCore', function($scope , $location , egCore) { - var id = egCore.hatch.getLoginSessionItem('eg.circ.last_patron'); - if (id) return $location.path('/circ/patron/' + id + '/checkout'); + var ids = egCore.hatch.getLoginSessionItem('eg.circ.recent_patrons') || []; + if (ids.length) + return $location.path('/circ/patron/' + ids[0] + '/checkout'); $scope.no_last = true; }]) diff --git a/Open-ILS/web/js/ui/default/staff/services/navbar.js b/Open-ILS/web/js/ui/default/staff/services/navbar.js index 713d9f39ec..1d90691956 100644 --- a/Open-ILS/web/js/ui/default/staff/services/navbar.js +++ b/Open-ILS/web/js/ui/default/staff/services/navbar.js @@ -116,6 +116,13 @@ angular.module('egCoreMod') $scope.op_changed = egCore.auth.OCtoken() ? true : false; $scope.username = egCore.auth.user().usrname(); $scope.workstation = egCore.auth.workstation(); + + egCore.org.settings('ui.staff.max_recent_patrons') + .then(function(s) { + var val = s['ui.staff.max_recent_patrons']; + $scope.showRecentPatron = val > 0; + $scope.showRecentPatrons = val > 1; + }); } } ); diff --git a/Open-ILS/web/js/ui/default/staff/services/patron_search.js b/Open-ILS/web/js/ui/default/staff/services/patron_search.js index 48859d850f..911e6534a5 100644 --- a/Open-ILS/web/js/ui/default/staff/services/patron_search.js +++ b/Open-ILS/web/js/ui/default/staff/services/patron_search.js @@ -74,6 +74,60 @@ function($q , $timeout , $location , egCore, egUser , $locale) { return $q.when(); } + service.getRecentPatrons = function() { + // avoid getting stuck in a show-recent loop + service.showRecent = false; + + if (service.maxRecentPatrons < 1) return $q.when(); + var patrons = + egCore.hatch.getLoginSessionItem('eg.circ.recent_patrons') || []; + + // Ensure the cached list is no bigger than the current config. + // This can happen if the setting changes while logged in. + patrons = patrons.slice(0, service.maxRecentPatrons); + + // add home_ou to the list of fleshed fields for recent patrons + var fleshFields = egUser.defaultFleshFields.slice(0); + fleshFields.push('home_ou'); + + var deferred = $q.defer(); + function getNext() { + if (patrons.length == 0) { + deferred.resolve(); + return; + } + egUser.get(patrons[0], {useFields : fleshFields}).then( + function(usr) { // fetch first user + deferred.notify(usr); + patrons.splice(0, 1); // remove first user from list + getNext(); + } + ); + } + + getNext(); + return deferred.promise; + } + + service.addRecentPatron = function(user_id) { + if (service.maxRecentPatrons < 1) return; + + // no need to re-track same user + if (service.current && service.current.id() == user_id) return; + + var patrons = + egCore.hatch.getLoginSessionItem('eg.circ.recent_patrons') || []; + patrons.splice(0, 0, user_id); // put this user at front + patrons.splice(service.maxRecentPatrons, 1); // remove excess + + // remove any other occurrences of this user, which may have been + // added before the most recent user. + var idx = patrons.indexOf(user_id, 1); + if (idx > 0) patrons.splice(idx, 1); + + egCore.hatch.setLoginSessionItem('eg.circ.recent_patrons', patrons); + } + // sets the primary display user, fetching data as necessary. service.setPrimary = function(id, user, force) { var user_id = id ? id : (user ? user.id() : null); @@ -82,9 +136,7 @@ function($q , $timeout , $location , egCore, egUser , $locale) { if (!user_id) return $q.reject(); - // when loading a new patron, update the last patron setting - if (!service.current || service.current.id() != user_id) - egCore.hatch.setLoginSessionItem('eg.circ.last_patron', user_id); + service.addRecentPatron(user_id); // avoid running multiple retrievals for the same patron, which // can happen during dbl-click by maintaining a single running @@ -389,6 +441,22 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egCore, selectedItems : function() {return []} } + // Max recents setting is loaded and scrubbed during egStartup. + // Copy it to a local variable here for ease of local access. + egCore.org.settings('ui.staff.max_recent_patrons').then(function(s) { + patronSvc.maxRecentPatrons = s['ui.staff.max_recent_patrons']; + }); + + // The first time we encounter the show-recent CGI param, put the + // service into show-recent mode. The first time recents are shown, + // the service is taken out of show-recent mode so the page does not + // get stuck in a show-recent loop. + if (patronSvc.showRecent === undefined + && Boolean($location.path().match(/search/)) + && Boolean($location.search().show_recent)) { + patronSvc.showRecent = true; + } + // Handle URL-encoded searches if ($location.search().search) { console.log('URL search = ' + $location.search().search); @@ -411,7 +479,7 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egCore, var propagate; var propagate_inactive; - if (patronSvc.lastSearch) { + if (patronSvc.lastSearch && !patronSvc.showRecent) { propagate = patronSvc.lastSearch.search; // home_ou needs to be treated specially propagate.home_ou = { @@ -457,6 +525,11 @@ function($scope, $q, $routeParams, $timeout, $window, $location, egCore, provider.get = function(offset, count) { var deferred = $q.defer(); + if (patronSvc.showRecent) { + // avoid getting stuck in show-recent mode + return patronSvc.getRecentPatrons(); + } + var fullSearch; if (patronSvc.urlSearch) { fullSearch = patronSvc.urlSearch; diff --git a/Open-ILS/web/js/ui/default/staff/services/startup.js b/Open-ILS/web/js/ui/default/staff/services/startup.js index 038eb2dfc2..603d040991 100644 --- a/Open-ILS/web/js/ui/default/staff/services/startup.js +++ b/Open-ILS/web/js/ui/default/staff/services/startup.js @@ -25,14 +25,15 @@ function($q, $rootScope, $location, $window, egIDL, egAuth, egEnv , egOrg var service = { promise : null } - // Load date/time format settings on all pages. Add more .push(...) - // calls to add more universal data-loading functions. + // Some org settings affect every page. Load them during startup. + // Other startup data loaders can be added by appending to egEnv.loaders. // egEnv.loaders functions must return a promise. egEnv.loaders.push( function() { return egOrg.settings([ 'webstaff.format.dates', 'webstaff.format.date_and_time', + 'ui.staff.max_recent_patrons', // affects navbar 'lib.timezone' ]).then( function(set) { @@ -40,6 +41,10 @@ function($q, $rootScope, $location, $window, egIDL, egAuth, egEnv , egOrg set['webstaff.format.dates'] || 'shortDate'; $rootScope.egDateAndTimeFormat = set['webstaff.format.date_and_time'] || 'short'; + + // default to 1 for backwards compat. + if (set['ui.staff.max_recent_patrons'] === null) + set['ui.staff.max_recent_patrons'] = 1 } ); } -- 2.11.0