Angular selfcheck WIP
authorBill Erickson <berickxx@gmail.com>
Thu, 27 Oct 2016 17:01:06 +0000 (13:01 -0400)
committerBill Erickson <berickxx@gmail.com>
Fri, 11 Aug 2017 19:20:25 +0000 (15:20 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/templates/staff/circ/selfcheck/index.tt2
Open-ILS/src/templates/staff/circ/selfcheck/t_checkout.tt2
Open-ILS/src/templates/staff/circ/selfcheck/t_login.tt2
Open-ILS/web/js/ui/default/staff/circ/selfcheck/app.js

index dff68f7..04be105 100644 (file)
@@ -2,6 +2,7 @@
   WRAPPER "staff/base.tt2";
   ctx.page_title = l("Self-Checkout"); 
   ctx.page_app = "egSelfCheckApp";
+  ctx.page_ctrl = "SelfCheckCtrl";
   ctx.hide_nav = 1;
 %]
 
 
 <script>
 angular.module('egCoreMod').run(['egStrings', function(s) {
+  s.CONFIRM_TIMEOUT_TITLE = 
+    "[% l('Inactivity Warning') %]";
+  s.CONFIRM_TIMEOUT_MSG = 
+    "[% l('Your login session will soon timeout due to inactivity.') %]";
+  s.CONFIRM_TIMEOUT_CONTINUE = "[% l('Continue Session') %]";
+  s.CONFIRM_TIMEOUT_LOGOUT = "[% l('Logout') %]";
 }]);
 </script>
 [% END %]
 
-<div ng-view></div>
+<div class="row" ng-if="!is_login_page()">
+  <div class="col-md-12">
+    <div class="row">
+      <div>[% l('Welcome, [_1]', '{{patron().first_given_name()}}') %]</div>
+    </div>
+    <div class="row">
+      <!-- TODO: header image stuff -->
+      <div class="col-md-5"></div>
+      <div class="col-md-2">
+        <input 
+          class="form-control"
+          focus-me="scanbox.focus" 
+          ng-model="scanbox.text"
+          ng-disabled="scanbox.disabled()"
+          type="text"/> 
+      </div>
+      <div class="col-md-5"></div>
+    </div>
+  </div>
+</div>
+
+<div class="row">
+  <div class="col-md-8">
+    <div ng-view></div>
+  </div>
+  <div class="col-md-4" ng-if="!is_login_page()">
+    <fieldset>
+      <legend>[% l('Items Checked Out') %]</legend>
+      <div>[% l('Total items this session: [_1]', 
+        '{{counts("session_circ")}}') %]</div>
+      <div>[% l('Total items on account: [_1]', 
+        '{{counts("total_circ")}}') %]</div>
+      <div><button class="btn btn-success">
+        [% l('View Items Out') %]</button></div>
+    </fieldset>
+    <fieldset>
+      <legend>[% l('Holds') %]</legend>
+      <div>[% l('You have [_1] item(s) ready for pickup', 
+        '{{counts("hold_ready")}}') %]</div>
+      <div>[% l('You have [_1] total holds', 
+        '{{counts("total_hold")}}') %]</div>
+      <div><button class="btn btn-success">
+        [% l('View Holds') %]</button></div>
+    </fieldset>
+    <fieldset>
+      <legend>[% l('Fines') %]</legend>
+      <div><button class="btn btn-success">
+        [% l('View Details') %]</button>
+      </div>
+    </fieldset>
+  </div>
+</div>
 
 [% END %]
index b34a166..3e15c44 100644 (file)
@@ -5,7 +5,8 @@
         <fieldset>
           <legend>[% l('Please log in with your username or library barcode.') %]</legend>
 
-          <form ng-submit="login(args)" name="sc-login-form" class="form-horizontal" role="form">
+          <form ng-submit="login(args)" name="sc-login-form" 
+            autocomplete="off" class="form-horizontal" role="form">
             <div class="form-group">
               <label class="col-md-4 control-label" for="login-username">[% l('Username or Barcode') %]</label>
               <div class="col-md-8">
index 4428364..d6c631a 100644 (file)
@@ -2,8 +2,8 @@
  * Self-Checkout App
  */
 
-angular.module('egSelfCheckApp', ['ngRoute', 'ui.bootstrap', 
-    'egCoreMod', 'egUiMod', 'ngToast'])
+angular.module('egSelfCheckApp', 
+    ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'ngToast'])
 
 .config(['ngToastProvider', function(ngToastProvider) {
     ngToastProvider.configure({
@@ -14,7 +14,6 @@ angular.module('egSelfCheckApp', ['ngRoute', 'ui.bootstrap',
 
 .config(function($routeProvider, $locationProvider, $compileProvider) {
     $locationProvider.html5Mode(true);
-    $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
@@ -68,8 +67,8 @@ angular.module('egSelfCheckApp', ['ngRoute', 'ui.bootstrap',
  * Self-Checkout Service
  */
 .factory('scSvc',
-       ['$q','$timeout','$location','$timeout','egCore',
-function($q , $timeout , $location , $timeout , egCore) {
+       ['$q','$timeout','$window','$location','$timeout','egCore','egConfirmDialog',
+function($q , $timeout , $window , $location , $timeout , egCore , egConfirmDialog) {
 
     var service = {
         login_timer : null,
@@ -83,12 +82,35 @@ function($q , $timeout , $location , $timeout , egCore) {
 
         // 20 second inactivity warning; total default timeout is 3 minutes.
         login_timeout_warning : 20000, 
+
+        session_circ_count : 0,
+        total_circ_count : 0,
+        hold_ready_count : 0,
+        total_hold_count : 0,
+
     };
 
+    service.show_timeout_warning = function() {
+        // TODO: force logout after warning timeout
+
+        egConfirmDialog.open(
+            egCore.strings.CONFIRM_TIMEOUT_TITLE, 
+            egCore.strings.CONFIRM_TIMEOUT_MSG, 
+            {   ok : function() { service.reset_login_timer() },
+                cancel : function() { service.logout_patron() }
+            },
+            egCore.strings.CONFIRM_TIMEOUT_CONTINUE,
+            egCore.strings.CONFIRM_TIMEOUT_LOGOUT
+        );
+
+        service.login_warning_timer = $timeout(
+            service.logout_patron, service.login_timeout_warning
+        );
+    }
 
     service.start_login_timer = function() {
         service.login_timer = $timeout(
-            service.login_timer_handler, service.login_timeout
+            service.show_timeout_warning, service.login_timeout
         );
         console.debug('starting patron login timer');
     }
@@ -96,70 +118,107 @@ function($q , $timeout , $location , $timeout , egCore) {
     service.reset_login_timer = function() {
         if (service.login_timer) {
             $timeout.cancel(service.login_timer);
+            service.login_timer = null;
+        }
+        if (service.login_warning_timer) {
+            $timeout.cancel(service.login_warning_timer);
+            service.login_warning_timer = null;
         }
         service.start_login_timer();
         console.debug('reset patron login timer');
     }
 
 
-    service.fetch_patron = function(username, barcode, deferred) {
+    service.fetch_patron = function(username, barcode) {
+        var evt;
 
-        egCore.net.request(
+        return egCore.net.request(
             'open-ils.actor', 
             'open-ils.actor.user.retrieve_id_by_barcode_or_username',
             egCore.auth.token(), barcode, username
         ).then(function(patron_id) {
 
-            if (egCore.evt.parse(patron_id)) {
-                deferred.reject();
-                return;
+            if (evt = egCore.evt.parse(patron_id)) {
+                console.warn(evt);
+                return $q.reject(evt);
             }
 
-            egCore.net.request(
+            return egCore.net.request(
                 'open-ils.actor', 
                 'open-ils.actor.user.fleshed.retrieve.authoritative',
                 egCore.auth.token(), patron_id
             ).then(function(patron) {
 
-                if (egCore.evt.parse(patron)) {
-                    deferred.reject();
-                    return;
+                if (evt = egCore.evt.parse(patron)) {
+                    console.warn(evt);
+                    return $q.reject(evt);
                 }
 
                 service.patron = patron;
-                deferred.resolve();
+                service.start_login_timer();
             });
         });
     }
 
     service.login_patron = function(username, password) {
-        var deferred = $q.defer();
 
         // TODO: test barcode regex
         var barcode = null;
 
         if (true) { // TODO: test password required
-            egCore.auth.verify({
+            return egCore.auth.verify({
                 username : username, 
                 barcode  : barcode,
                 password : password
-            }).then(
-                function() {
-                    service.fetch_patron(username, barcode, deferred);
-                },
-                function() { deferred.reject() /* verify failed */ }
-            );
+            }).then(function() {
+                return service.fetch_patron(username, barcode);
+            });
         } else {
-            service.fetch_patron(username, barcode, deferred);
+            return service.fetch_patron(username, barcode);
         }
-
-        return deferred.promise;
     }
 
+    service.logout_patron = function() {
+        // force a page reload to clear all cached data.
+        $window.location.href = $location.absUrl().replace(
+            /\/selfcheck\/.*/, '/selfcheck/login');
+    }
 
     return service;
 }])
 
+/* Page-level parent controller for all self-check controllers.
+ * Handles navigation, scanbox, and page wrapper display.
+ * This controller is instantiated once per page load, not per navigation.
+ */
+
+.controller('SelfCheckCtrl',
+       ['$scope','$q','$location','egCore','scSvc',
+function($scope,  $q,  $location , egCore,  scSvc) {
+
+    // data shared with sub-scopes
+    $scope.counts = function(type) {
+        return scSvc[type + '_count'];
+    }
+
+    $scope.is_login_page = function() {
+        return $location.path() == '/circ/selfcheck/login';
+    }
+
+    $scope.scanbox = {
+        text : '',
+        focus : false,
+        disabled : function() {
+            // TODO: inactive barcode, etc.
+            return false;
+        }
+    }
+
+    $scope.patron = function() { return scSvc.patron }
+
+}])
+
+
 /**
  * Manages tabbed patron view.
  * This is the parent scope of all patron tab scopes.
@@ -176,7 +235,6 @@ function($scope,  $q,  $location , egCore,  scSvc) {
 
         scSvc.login_patron(args.username, args.password).then(
             function() {
-                console.log('HERE');
                 $location.path('/circ/selfcheck/checkout');
             },
             function() {
@@ -197,7 +255,8 @@ function($scope,  $q,  $location , egCore,  scSvc) {
         return;
     }
 
-    $scope.patron = scSvc.patron;
+    scSvc.reset_login_timer();
+    $scope.scanbox.focus = true;
 
 }])