JBAS-1728 SCKO misc. additions and repairs
authorBill Erickson <berickxx@gmail.com>
Wed, 28 Jun 2017 20:52:39 +0000 (16:52 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 21 Mar 2019 19:46:23 +0000 (15:46 -0400)
* Display batch renewal status info within the items out page
* Adds a login page cancel button
* Fixes various issues with the already-seen barcode handling
* Prevent batch renewal attempst on already seen barcodes
* Avoid displaying batch-renewed circs in the session circs list

Signed-off-by: Bill Erickson <berickxx@gmail.com>
KCLS/openils/var/templates_kcls/circ/selfcheck/circ_page.tt2
KCLS/openils/var/templates_kcls/circ/selfcheck/patron_login.tt2
Open-ILS/web/js/dojo/openils/circ/nls/selfcheck.js
Open-ILS/web/js/ui/kcls/circ/selfcheck/selfcheck.js

index e46bc72..8f551a4 100644 (file)
 
 <div class="scko-table">
 <div class="row">
+  <div id='scko-renewal-alerts' class='col-xs-12 oils-selfck-status-div status_box'>
+  </div>
+</div>
+<div class="row">
   <div class="col-xs-12">
     <table class="table scko-table-striped">
       <tbody id='oils-selfck-circ-out-tbody'>
index 84e8d2f..bb2c419 100644 (file)
       <div class="col-md-10">
         <label class="control-label" for="patron-login-password">Example 0926</label>
         <div class="row">
-          <div class="col-md-7">
+          <div class="col-md-6">
             <div class="form-group">
               <input type="password" id='patron-login-password' class="form-control" placeholder="Enter your PIN here"/>
             </div>
           </div>
-          <div class="col-xs-6 col-md-3">
+          <div class="col-xs-6 col-md-2">
             <div class="form-group">
-              <button class="btn btn-success" if="patron-login-submit" onfocus="checkLogin(); 
+              <button class="btn btn-success" onfocus="checkLogin(); 
                 selfCheckMgr.loginPatron(dojo.byId('patron-login-username').value,dojo.byId('patron-login-password').value);">
-                GO >>>
+                GO &gt;&gt;&gt;
               </button>
             </div>
           </div>
+          <div class="col-xs-6 col-md-2">
+            <div class="form-group">
+              <!-- patron is not logged in, but cancel calls logout both
+                to clear the form (particularly of passwords) and to allow
+                for the necessary page redirects (e.g. return-to url). -->
+              <button class="btn btn-warning" onclick="selfCheckMgr.logoutPatron();">
+                Cancel
+              </button>
+            </div>
+          </div>
+        </div>
+        <div class="row">
           <div class="col-md-offset-3 col-xs-6 pad-vert">
             <button id="scko-contrast-toggle-button" class="btn btn-default btn-high-contrast"
             onclick="swapStyleSheet('[% ctx.media_prefix %]/css/skin/kcls/selfcheck-high-contrast.css',
@@ -45,4 +57,4 @@
     </div>
   </div>
 </div>
-</div>
\ No newline at end of file
+</div>
index cf15eab..d394b58 100644 (file)
@@ -22,7 +22,7 @@
     "WORKSTATION_EXISTS" : "This workstation has already been registered.  Would you like to use it for this self-check station?",
     "CC_PAYABLE_BALANCE" : "Total amount to pay: $${0}",
     "TOTAL_FINES_SELECTED" : "Selected total: $${0}",
-    "DOUBLE_SCAN" : "${0}  was already successfully processed.",
+    "DOUBLE_SCAN" : "Item ${0} was already processed.",
     "WELCOME_BANNER" : "Welcome, ${0}",
     "ENTER_PASSWORD" : "Please enter your password",
     "PLEASE_LOGIN" : "Please log in with your username or library barcode.",
index d867717..03aae1d 100644 (file)
@@ -21,8 +21,7 @@ var selfckWarningSetup = false;
 var selfckWarningTimer;
 var selfCheckManager;
 
-var barcodesSeen = {};
-var scannedBarcode = 0;
+var seenBarcodes = {};
 
 var selfCheckMgr;
 var itemsOutCirc = [];
@@ -35,7 +34,7 @@ var thankYouPageTimeout = 5000;
 
 // Ignore duplicate barcode scans that happen within this many ms.
 // Dupe scans that happen farther apart result in a patron warning.
-var dblScanWarnTimeout = 5000;
+var dblScanWarnTimeout = 2000;
 
 const SET_BARCODE_REGEX = 'opac.barcode_regex';
 const SET_PATRON_TIMEOUT = 'circ.selfcheck.patron_login_timeout';
@@ -532,24 +531,32 @@ SelfCheckManager.prototype.drawCircPage = function() {
     this.updateScanBox({
         msg : 'Please enter an item barcode', // TODO i18n
         handler : function(barcode) {
-          barcodesSeen[scannedBarcode] = barcode;
-          var selfckScanbox = document.getElementById('selfckScanBox');
-          if(barcodesSeen[scannedBarcode - 1] == barcode ){
-            if(new Date().getTime() - timeScanned < dblScanWarnTimeout){
-                console.log("Date: " + new Date().getTime());
-                console.log("Time scanned: " + timeScanned);
-                console.log(new Date().getTime() - timeScanned);
-              var message = dojo.string.substitute(localeStrings.DOUBLE_SCAN, [barcode]);
-              dojo.byId('oils-selfck-status-div').innerHTML = message;
-            };
-            selfckScanbox.value = '';
-            selfckScanbox.focus();
-          } else {
-              scannedBarcode++;
-              timeScanned = new Date().getTime();
-              switchTo('step3');
-              self.checkout(barcode);
-          }
+
+            var curTime = new Date().getTime();
+            var prevScanTime = seenBarcodes[barcode];
+
+            if (prevScanTime) {
+                console.log('barcode previously scanned at ' + 
+                    prevScanTime + ' ; current time ' + curTime );
+
+                // This barcode has already been seen
+                var selfckScanbox = document.getElementById('selfckScanBox');
+
+                if (curTime - prevScanTime > dblScanWarnTimeout) {
+                    // this barcode was scanned more than dblScanWarnTimeout
+                    // milliseconds ago -- alert the patron.
+                    dojo.byId('oils-selfck-status-div').innerHTML = 
+                        dojo.string.substitute(
+                            localeStrings.DOUBLE_SCAN, [barcode]);
+                }
+
+                selfckScanbox.value = '';
+                selfckScanbox.focus();
+            } else {
+                seenBarcodes[barcode] = curTime;
+                switchTo('step3');
+                self.checkout(barcode);
+            }
         }
     });
 
@@ -597,6 +604,7 @@ SelfCheckManager.prototype.updateFinesSummary = function() {
 SelfCheckManager.prototype.drawItemsOutPage = function() {
     switchTo('step3','step3d');
     dojo.byId('oils-selfck-status-div').innerHTML = ''; // reset notices
+    dojo.byId('scko-renewal-alerts').innerHTML = '';
 
     // Reset items checked out in case it changed
     this.circSummary = undefined;
@@ -647,9 +655,11 @@ function handleCheckedItems(circs) {
     dojo.forEach(circs, function(circ) {
 
         var row = self.outTemplate.cloneNode(true);
-        row.setAttribute('copy_barcode', circ.copy.barcode());
 
-        self.byName(row,'barcode').innerHTML = circ.copy.barcode();
+        var barcode = circ.copy.barcode();
+        row.setAttribute('copy_barcode', barcode);
+
+        self.byName(row, 'barcode').innerHTML = barcode;
         self.byName(row, 'title').innerHTML = circ.record.title();
         self.byName(row, 'author').innerHTML = circ.record.author();
         self.byName(row, 'remaining_renewals').innerHTML = circ.circ.renewal_remaining();
@@ -661,10 +671,14 @@ function handleCheckedItems(circs) {
             dojo.date.stamp.fromISOString(circ.circ.due_date()),
             {selector: 'date', fullYear: true}
         );
-        if(circ.circ.renewal_remaining() < 1) {
+        
+        // Disallow renewals of items with no renewals remaining or 
+        // items that were already scanned in the current session.
+        if (circ.circ.renewal_remaining() < 1 || seenBarcodes[barcode]) {
             self.byName(row, 'renew_selector').checked = false;
             self.byName(row, 'renew_selector').setAttribute('disabled', true);
         }
+
         self.byName(row,'format').innerHTML = circ.record.types_of_resource()[0];
         self.itemsOutTbody.appendChild(row);
     });
@@ -714,27 +728,36 @@ SelfCheckManager.prototype.renewItems = function() {
         renew_count++;
         checkbox.checked = false; // de-select all
 
-        var stat = self.renew(row.getAttribute('copy_barcode'), false, true);
-        if (stat.success) success_count++;
+        var barcode = row.getAttribute('copy_barcode');
+        var stat = self.renew(barcode, false, true);
+
+        if (stat.success) {
+            // prevent any more renewal attempts (batch or scan) on this 
+            // item by adding it to the list of already seen barcodes.
+            seenBarcodes[barcode] = new Date().getTime();
+            success_count++;
+        }
     });
 
-    this.drawCircPage();
+    //this.drawCircPage();
+    this.drawItemsOutPage();
 
     // Display a generic success/failure batch renewal notification
-    if (success_count == renew_count) {
-        this.handleAlert(
-            dojo.string.substitute(
-                localeStrings.BATCH_RENEW_SUCCESS, [success_count]),
-            false, 'checkout-success'
-        );
-
-    } else {
-        this.handleAlert(
-            dojo.string.substitute(
-                localeStrings.BATCH_RENEW_FAILURE, 
-                [renew_count - success_count]
-            ), true, 'checkout-failure');
+    // Renewal messages appear on the items-out page, not the checkouts
+    // page, so the message is manually inserted into the DOM instead
+    // of using the existing handleAlert message handling.
+    var msg = dojo.string.substitute(
+        localeStrings.BATCH_RENEW_SUCCESS, [success_count]);
+    var sound = 'checkout-success';
+
+    if (success_count < renew_count) {
+        msg = dojo.string.substitute(
+            localeStrings.BATCH_RENEW_FAILURE, [renew_count - success_count]);
+        sound = 'checkout-failure';
     }
+
+    dojo.byId('scko-renewal-alerts').innerHTML = msg;
+    this.handleAlert('', false, sound);
 }
 
 
@@ -1142,12 +1165,16 @@ SelfCheckManager.prototype.handleXactResult = function(action, item, result, isB
         } else if(action == 'renew') {
 
             displayText = dojo.string.substitute(localeStrings.RENEW_SUCCESS, [item]);
-            this.displayCheckout(result, 'renew');
+
+            // Avoid displaying batch renewal circs in the session circs
+            // page.  The are displayed in session receipts and emails,
+            // though, so they get added to this.checkouts (below).
+            if (!isBatch) this.displayCheckout(result, 'renew');
         }
 
         success = true;
-        this.checkouts.push({circ : result.payload.circ.id()});
         sound = 'checkout-success';
+        this.checkouts.push({circ : result.payload.circ.id()});
         this.updateScanBox();
 
     } else if(result.textcode == 'OPEN_CIRCULATION_EXISTS' && action == 'checkout') {
@@ -1662,7 +1689,6 @@ SelfCheckManager.prototype.printFinesReceipt = function(callback) {
  */
 SelfCheckManager.prototype.logoutPatron = function(print, email) {
 
-    var scannedBarcode = 0;
     if(print && this.checkouts.length) {
         progressDialog.show(true); // prevent patron from clicking logout link twice
         this.printSessionReceipt(selfCheckManager.processLogout);