From 8c1bb27ed52ec0d95fa71e3e9e7bde61f9edea14 Mon Sep 17 00:00:00 2001 From: Mike Rylander Date: Thu, 8 Jun 2017 17:55:41 -0400 Subject: [PATCH] offline: Add light-weight tablesorter; Enable barcode checking; Add confirmation before clearing pending transactions; Improve layout of offline interfaces Signed-off-by: Mike Rylander --- Open-ILS/src/templates/staff/base_js.tt2 | 5 + Open-ILS/src/templates/staff/offline-interface.tt2 | 124 ++++++++++++--------- Open-ILS/web/js/ui/default/staff/Gruntfile.js | 2 + Open-ILS/web/js/ui/default/staff/offline.js | 70 +++++++++--- Open-ILS/web/js/ui/default/staff/package.json | 1 + 5 files changed, 138 insertions(+), 64 deletions(-) diff --git a/Open-ILS/src/templates/staff/base_js.tt2 b/Open-ILS/src/templates/staff/base_js.tt2 index 351a246dde..edc16e0ffd 100644 --- a/Open-ILS/src/templates/staff/base_js.tt2 +++ b/Open-ILS/src/templates/staff/base_js.tt2 @@ -12,6 +12,7 @@ UpUp.start({ '[% ctx.media_prefix %]/js/ui/default/staff/build/css/ngToast-animations.min.css', '[% ctx.media_prefix %]/js/ui/default/staff/build/css/tree-control.css', '[% ctx.media_prefix %]/js/ui/default/staff/build/css/tree-control-attribute.css', + '[% ctx.media_prefix %]/js/ui/default/staff/build/css/tablesort.css', '[% ctx.base_path %]/staff/css/print.css', '[% ctx.base_path %]/staff/css/cat.css', '[% ctx.base_path %]/staff/css/style.css', @@ -31,6 +32,7 @@ UpUp.start({ '[% ctx.media_prefix %]/js/ui/default/staff/build/js/angular-tree-control.js', '[% ctx.media_prefix %]/js/ui/default/staff/build/js/iframeResizer.min.js', '[% ctx.media_prefix %]/js/ui/default/staff/build/js/ng-order-object-by.js', + '[% ctx.media_prefix %]/js/ui/default/staff/build/js/angular-tablesort.js', '[% ctx.media_prefix %]/js/ui/default/staff/build/js/lovefield.min.js', '[% ctx.media_prefix %]/js/ui/default/staff/build/fonts/glyphicons-halflings-regular.woff', '[% ctx.media_prefix %]/js/dojo/opensrf/JSON_v1.js', @@ -166,7 +168,10 @@ UpUp.start({ s.PATRON_NOT_FOUND = "[% l('Patron not found') %]"; s.PATRON_BLOCKED = "[% l('Patron blocked') %]"; s.BAD_BARCODE = "[% l('Bad item barcode') %]"; + s.BAD_PATRON_BARCODE = "[% l('Bad patron barcode') %]"; s.ITEM_NOT_FOUND = "[% l('Item not found') %]"; + s.CONFIRM_CLEAR_PENDING = "[% l('Clear pending transactions') %]"; + s.CONFIRM_CLEAR_PENDING_BODY = "[% l('Are you certain you want to clear these pending offline transactions? This action is not reversable, and they cannot be recovered after clearing!') %]"; }]); diff --git a/Open-ILS/src/templates/staff/offline-interface.tt2 b/Open-ILS/src/templates/staff/offline-interface.tt2 index 0697759f2a..d75a074f72 100644 --- a/Open-ILS/src/templates/staff/offline-interface.tt2 +++ b/Open-ILS/src/templates/staff/offline-interface.tt2 @@ -52,6 +52,25 @@
+ [% l('Due Date:') %] +
+
+ +
+
+ +
+
+ +
+
+
[% l('Patron barcode:') %]
@@ -108,27 +127,12 @@
-
-
- [% l('Due Date:') %] +
+
- -
-
- -
-
- -
-
- + +
@@ -171,46 +175,50 @@
- [% l('Patron barcode:') %] + [% l('Due Date:') %]
-
- +
+ +
+
+
- [% l('Item Barcode:') %] + [% l('Patron barcode:') %]
- +
- [% l('Due Date:') %] -
-
- + [% l('Item Barcode:') %]
-
- +
+
-
+
+
+ + +
@@ -250,7 +258,7 @@
-
+
[% l('Use count:') %] @@ -260,7 +268,7 @@
-
+
[% l('Item Barcode:') %] @@ -271,9 +279,13 @@
-
+
+
+ + +
@@ -314,27 +326,31 @@
- [% l('Item Barcode:') %] + [% l('Checkin Date:') %]
- +
- [% l('Checkin Date:') %] + [% l('Item Barcode:') %]
- +
-
+
+
+ + +
@@ -446,23 +462,27 @@
- +
- - + + + + - + - + + @@ -531,7 +551,7 @@ ng-disabled="!logged_in || (!xact.command.patron_barcode && xact.command.user.card.barcode)" ng-click="retrievePatron(xact.command.patron_barcode)">[% l('Patron') %] @@ -554,6 +574,7 @@ + + [% END %]
diff --git a/Open-ILS/web/js/ui/default/staff/Gruntfile.js b/Open-ILS/web/js/ui/default/staff/Gruntfile.js index e5941960fa..db8590b0f5 100644 --- a/Open-ILS/web/js/ui/default/staff/Gruntfile.js +++ b/Open-ILS/web/js/ui/default/staff/Gruntfile.js @@ -37,6 +37,7 @@ module.exports = function(grunt) { 'node_modules/iframe-resizer/js/iframeResizer.map', 'node_modules/iframe-resizer/js/iframeResizer.contentWindow.min.js', 'node_modules/angular-order-object-by/src/ng-order-object-by.js', + 'node_modules/angular-tablesort/js/angular-tablesort.js', 'node_modules/lovefield/dist/lovefield.min.js', 'node_modules/lovefield/dist/lovefield.min.js.map' ] @@ -56,6 +57,7 @@ module.exports = function(grunt) { 'node_modules/ngtoast/dist/ngToast-animations.min.css', 'node_modules/angular-tree-control/css/tree-control.css', 'node_modules/angular-tree-control/css/tree-control-attribute.css', + 'node_modules/angular-tablesort/tablesort.css', ] }] }, diff --git a/Open-ILS/web/js/ui/default/staff/offline.js b/Open-ILS/web/js/ui/default/staff/offline.js index 1c08568140..c29b393b58 100644 --- a/Open-ILS/web/js/ui/default/staff/offline.js +++ b/Open-ILS/web/js/ui/default/staff/offline.js @@ -4,7 +4,7 @@ lf.isOffline = true; -angular.module('egOffline', ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'ngToast']) +angular.module('egOffline', ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'ngToast', 'tableSort']) .config( ['$routeProvider','$locationProvider','$compileProvider', @@ -131,12 +131,19 @@ function($routeProvider , $locationProvider , $compileProvider) { } return $q.reject(); }).then(function() { + var creator_list = [$q.when()]; angular.forEach($scope.sessions, function (s) { s.total = 0; + s.org = egCore.org.get(s.org).shortname(); + creator_list.push(egCore.pcrud.retrieve('au',s.creator).then(function(u) { + s.creator = u.family_name(); + })); angular.forEach(s.scripts, function(sc) { s.total += sc.count; }); }); + + return $q.all(creator_list); }); } @@ -163,7 +170,7 @@ function($routeProvider , $locationProvider , $compileProvider) { } ).then(function(res) { if (res.data.ilsevent == "0") { - return $scope.clear_pending().then(function() { + return $scope.clear_pending(true).then(function() { return $scope.refreshSessions(); }); } else { @@ -232,8 +239,8 @@ function($routeProvider , $locationProvider , $compileProvider) { ]) .controller('OfflineCtrl', - ['$q','$scope','$location','$window','egCore','egLovefield','$routeParams','$timeout','$http','ngToast', - function($q , $scope , $location , $window , egCore , egLovefield , $routeParams , $timeout , $http , ngToast) { + ['$q','$scope','$location','$window','egCore','egLovefield','$routeParams','$timeout','$http','ngToast','egConfirmDialog', + function($q , $scope , $location , $window , egCore , egLovefield , $routeParams , $timeout , $http , ngToast , egConfirmDialog) { $scope.active_tab = $routeParams.tab || 'checkout'; $scope.blocked_patron = null; @@ -265,9 +272,16 @@ function($routeProvider , $locationProvider , $compileProvider) { })[0].name; } + $scope.changeCheck = function () { + $scope.strict_barcode = !$scope.strict_barcode; + $scope.do_check_changed = true; + egCore.hatch.setItem('eg.offline.strict_barcode', $scope.strict_barcode) + } + $scope.changePrint = function () { $scope.do_print = !$scope.do_print; $scope.do_print_changed = true; + egCore.hatch.setItem('eg.offline.print_receipt', $scope.do_print) } $scope.logged_in = egCore.auth.token() ? true : false; @@ -275,6 +289,18 @@ function($routeProvider , $locationProvider , $compileProvider) { if (!$scope.logged_in && $routeParams.tab == 'session') $scope.active_tab = 'checkout'; + egCore.hatch.getItem('eg.offline.print_receipt') + .then(function(setting) { + $scope.do_print = setting; + if (setting !== undefined) $scope.do_print_changed = true; + }); + + egCore.hatch.getItem('eg.offline.strict_barcode') + .then(function(setting) { + $scope.strict_barcode = setting; + if (setting !== undefined) $scope.do_check_changed = true; + }); + egCore.hatch.getItem('eg.workstation.all') .then(function(all) { if (all && all.length) { @@ -382,14 +408,28 @@ function($routeProvider , $locationProvider , $compileProvider) { }); } - $scope.clear_pending = function () { - return egLovefield.destroyPendingOfflineXacts().then(function () { - return $scope.retrieve_pending(); + $scope.clear_pending = function (skip_confirm) { + if (skip_confirm) { + return egLovefield.destroyPendingOfflineXacts().then(function () { + return $scope.retrieve_pending(); + }); + } + return egConfirmDialog.open( + egCore.strings.CONFIRM_CLEAR_PENDING, + egCore.strings.CONFIRM_CLEAR_PENDING_BODY, + {} + ).result.then(function() { + return egLovefield.destroyPendingOfflineXacts().then(function () { + return $scope.retrieve_pending(); + }); }); + } $scope.retrieve_pending(); $scope.$watch('active_tab', function (n,o) { + if (n != o && !$scope.do_check_changed && n != 'checkout') $scope.strict_barcode = false; + if (n != o && !$scope.do_check_changed && n == 'checkout') $scope.strict_barcode = true; if (n != o && !$scope.do_print_changed && n != 'checkout') $scope.do_print = false; if (n != o && !$scope.do_print_changed && n == 'checkout') $scope.do_print = true; if (n != o && n == 'session') $scope.retrieve_pending(); @@ -418,6 +458,7 @@ function($routeProvider , $locationProvider , $compileProvider) { $scope.resetDueDate = function (xtype) { $scope.shared.due_date = new Date(); + $scope.shared.due_date.setDate($scope.shared.due_date.getDate() + parseInt($scope.shared.due_date_offset)); } $scope.notEnough = function (xtype) { @@ -482,6 +523,15 @@ function($routeProvider , $locationProvider , $compileProvider) { var pbarcode = $scope[xtype].patron_barcode; var backdate = $scope[xtype].backdate; + if ($scope.strict_barcode && pbarcode) { + if (!check_barcode(pbarcode)) { + $scope.bad_barcode = xtype; + ngToast.warning(egCore.strings.BAD_PATRON_BARCODE); + egCore.audio.play('warning.offline.bad_barcode'); + return; + } + } + if ($scope.strict_barcode && $scope[xtype].barcode) { if (!check_barcode($scope[xtype].barcode)) { $scope.bad_barcode = xtype; @@ -496,12 +546,6 @@ function($routeProvider , $locationProvider , $compileProvider) { var now = new Date().getTime(); now = now / 1000; - if ($scope.shared.due_date_offset) { - var due = parseInt(now * 1000); - due += parseInt($scope.shared.due_date_offset) * 86400000; - $scope.shared.due_date = new Date(due); - } - if ($scope[xtype].noncat_type) $scope[xtype].noncat = 1; if ($scope.shared.due_date && (xtype == 'checkout' || xtype == 'renew')) { diff --git a/Open-ILS/web/js/ui/default/staff/package.json b/Open-ILS/web/js/ui/default/staff/package.json index 6a6a3b0797..c487f71353 100644 --- a/Open-ILS/web/js/ui/default/staff/package.json +++ b/Open-ILS/web/js/ui/default/staff/package.json @@ -15,6 +15,7 @@ "angular-mocks": "~1.5.0", "angular-route": "~1.5.0", "angular-tree-control": "~0.2.28", + "angular-tablesort": "^1.4.1", "angular-order-object-by": "rxfork/ngOrderObjectBy#npm", "lovefield": "*", "bootstrap": "~3.3.6", -- 2.11.0
[% l('Description') %][% l('Date Created') %][% l('Organization') %][% l('Created By') %][% l('Description') %][% l('Date Created') %] [% l('Upload Count') %] [% l('Transactions Processed') %][% l('Date Completed') %][% l('Date Completed') %]
{{ses.org}}{{ses.creator}} {{ses.description}} {{createDate(ses.create_time, true) | date:'short'}} {{ses.total}}