From: Jason Etheridge Date: Wed, 16 Feb 2011 17:43:52 +0000 (-0500) Subject: KCLS local oils_web templates/javascript/css from devcatalog X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=327844eb6a5319664999db24fc198bf0b0ad7b46;p=evergreen%2Fequinox.git KCLS local oils_web templates/javascript/css from devcatalog --- diff --git a/Open-ILS/examples/oils_web.xml.example b/Open-ILS/examples/oils_web.xml.example index 60f1573203..5e09bc578c 100644 --- a/Open-ILS/examples/oils_web.xml.example +++ b/Open-ILS/examples/oils_web.xml.example @@ -23,6 +23,7 @@ a path in front of the default template path --> + /openils/var/web/local_templates /openils/var/web/templates diff --git a/Open-ILS/web/css/skin/kcls/selfcheck.css b/Open-ILS/web/css/skin/kcls/selfcheck.css new file mode 100644 index 0000000000..2a5dc794d8 --- /dev/null +++ b/Open-ILS/web/css/skin/kcls/selfcheck.css @@ -0,0 +1,208 @@ +@charset "utf-8"; +/* CSS Document */ + +html, body { + margin:0; + font-family: Arial, Helvetica, sans-serif; + font-size: 18px; + background:#fff; + width:100%; +} + +img { + border: none; +} + +a { + color: #003399; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +h1 { + margin:0; + margin-bottom: 5px; + font-size: 22px; + font-weight:normal; +} + +h2 { + margin:0; + margin-bottom: 5px; + font-size: 20px; + font-weight:bold; +} + +#header { + color: #bda964; + font-weight:bold; + padding: 12px 0px 9px 17px; + width: 694px; + margin: auto; +} + +#content-wrapper { + background: white; +} + +#main-content { + width: 694px; + margin:auto; + padding-left:17px; +} + +.checkout { + font-size:18px; +} + +.checkout h1 { + font-size:36px; +} + +.checkout h2 { + font-size:24px; +} + +.checkout .sidebar h3 { + font-size: 19px; + margin:0; + padding-left:3px; +} + +.checkout .sidebar a { + font-size:18px; +} + +.checkout .sidebar a span { + font-weight:bold; +} + +.checkout .sidebar p { + margin:4px 0px; + padding:3px; +} + +.checkout .sidebar div, .checkout .sidebar p { + font-size: 18px; + line-height: 1em; +} + +.checkout input[type=text], .checkout input[type=password] { + border: 2px solid black; + width:300px; + height:22px; + padding:2px; + padding-top:1px; + margin:0px; + font-size:18px; +} + +.checkout .sidebar { + background: #b0b0b0; + border-left:2px ridge #eee; + border-right:2px ridge #eee; + border-bottom:2px ridge #eee; + padding:10px 7px; +} + +.checkout .sidebar .top { + float:right; + padding-right:5px; +} + +.checkout .sidebar .greet { + clear:both; + padding:15px 3px; +} + +.checkout .sidebar .selected { + background:#999 +} + +.checkout .header1 { + height:108px; + border-bottom:1px solid #a83135; + padding-top:20px; +} + +.checkout .userid { + width:200px !important; + font-size:18px; + font-weight:bold; + padding:5px 6px 6px 6px !important; + border:2px solid black !important; + background: none !important; + margin:0 !important; +} + +.checkout .item_table { + border-collapse: collapse; +} + +.checkout .item_table td { + font-size:18px; + border:2px solid black; + text-align: left; +} + +.checkout .item_table table td.label { + font-weight:bold; + text-transform: uppercase; + text-align: right; + white-space:nowrap; + padding-right:5px; + width:1px; +} + +.checkout .item_table table td { + border:none; +} + +.checkout #back_button:hover { + text-decoration: none; +} + +.checkout .status_box { + color:red; + font-weight:bold; + height:20px; +} + +.checkout .oils-selfck-status-div { + height:inherit !important; + vertical-align:inherit !important; + font-size: 18px; + font-weight: bold; + color: red; +} + +#oils-base-body-block { + height: auto; +} + +body .dijitAlignClient { + position:inherit; +} + +.dijitLayoutContainer { + position: inherit; +} + +#oils-base-content-block { + height: auto !important; + width: auto !important; + padding:0; +} + +#oils-base-main-block { + height: auto !important; + width: auto !important; +} + +#oils-base-header-block { + width:0px !important; +} + diff --git a/Open-ILS/web/js/ui/kcls/circ/selfcheck/floating.js b/Open-ILS/web/js/ui/kcls/circ/selfcheck/floating.js new file mode 100644 index 0000000000..863cde81e9 --- /dev/null +++ b/Open-ILS/web/js/ui/kcls/circ/selfcheck/floating.js @@ -0,0 +1,223 @@ +/* Script by: www.jtricks.com + * Version: 20071017 + * Latest version: + * www.jtricks.com/javascript/navigation/floating.html + */ +var floatingMenuId = 'floatdiv'; +var floatingMenu = +{ + targetX: -250, + targetY: -75, + + hasInner: typeof(window.innerWidth) == 'number', + hasElement: typeof(document.documentElement) == 'object' + && typeof(document.documentElement.clientWidth) == 'number', + + menu: + document.getElementById + ? document.getElementById(floatingMenuId) + : document.all + ? document.all[floatingMenuId] + : document.layers[floatingMenuId] +}; + +floatingMenu.move = function () +{ + floatingMenu.menu.style.left = floatingMenu.nextX + 'px'; + floatingMenu.menu.style.top = floatingMenu.nextY + 'px'; +} + +floatingMenu.computeShifts = function () +{ + var de = document.documentElement; + + floatingMenu.shiftX = + floatingMenu.hasInner + ? pageXOffset + : floatingMenu.hasElement + ? de.scrollLeft + : document.body.scrollLeft; + if (floatingMenu.targetX < 0) + { + floatingMenu.shiftX += + floatingMenu.hasElement + ? de.clientWidth + : document.body.clientWidth; + } + + floatingMenu.shiftY = + floatingMenu.hasInner + ? pageYOffset + : floatingMenu.hasElement + ? de.scrollTop + : document.body.scrollTop; +floatingMenu.shiftY = ( floatingMenu.shiftY < 76 ) ? 76 : +floatingMenu.shiftY; + if (floatingMenu.targetY < -75) + { + if (floatingMenu.hasElement && floatingMenu.hasInner) + { + // Handle Opera 8 problems + floatingMenu.shiftY += + de.clientHeight > window.innerHeight + ? window.innerHeight + : de.clientHeight + } + else + { + floatingMenu.shiftY += + floatingMenu.hasElement + ? de.clientHeight + : document.body.clientHeight; + } + } +} + +floatingMenu.calculateCornerX = function() +{ + return 0; + if (floatingMenu.targetX != 'center') + return floatingMenu.shiftX + floatingMenu.targetX; + + var width = parseInt(floatingMenu.menu.offsetWidth); + + var cornerX = + floatingMenu.hasElement + ? (floatingMenu.hasInner + ? pageXOffset + : document.documentElement.scrollLeft) + + (document.documentElement.clientWidth - width)/2 + : document.body.scrollLeft + + (document.body.clientWidth - width)/2; + return cornerX; +}; + +floatingMenu.calculateCornerY = function() +{ + if (floatingMenu.targetY != 'center') + return floatingMenu.shiftY + floatingMenu.targetY; + + var height = parseInt(floatingMenu.menu.offsetHeight); + + // Handle Opera 8 problems + var clientHeight = + floatingMenu.hasElement && floatingMenu.hasInner + && document.documentElement.clientHeight + > window.innerHeight + ? window.innerHeight + : document.documentElement.clientHeight + + var cornerY = + floatingMenu.hasElement + ? (floatingMenu.hasInner + ? pageYOffset + : document.documentElement.scrollTop) + + (clientHeight - height)/2 + : document.body.scrollTop + + (document.body.clientHeight - height)/2; + return cornerY; +}; + +floatingMenu.doFloat = function() +{ + // Check if reference to menu was lost due + // to ajax manipuations + if (!floatingMenu.menu) + { + menu = document.getElementById + ? document.getElementById(floatingMenuId) + : document.all + ? document.all[floatingMenuId] + : document.layers[floatingMenuId]; + + initSecondary(); + } + + var stepX, stepY; + + floatingMenu.computeShifts(); + + var cornerX = floatingMenu.calculateCornerX(); + + var stepX = (cornerX - floatingMenu.nextX) * .07; + if (Math.abs(stepX) < .5) + { + stepX = cornerX - floatingMenu.nextX; + } + + var cornerY = floatingMenu.calculateCornerY(); + + var stepY = (cornerY - floatingMenu.nextY) * .07; + if (Math.abs(stepY) < .5) + { + stepY = cornerY - floatingMenu.nextY; + } + + if (Math.abs(stepX) > 0 || + Math.abs(stepY) > 0) + { + floatingMenu.nextX += stepX; + floatingMenu.nextY += stepY; + floatingMenu.move(); + } + + setTimeout('floatingMenu.doFloat()', 20); +}; + +// addEvent designed by Aaron Moore +floatingMenu.addEvent = function(element, listener, handler) +{ + if(typeof element[listener] != 'function' || + typeof element[listener + '_num'] == 'undefined') + { + element[listener + '_num'] = 0; + if (typeof element[listener] == 'function') + { + element[listener + 0] = element[listener]; + element[listener + '_num']++; + } + element[listener] = function(e) + { + var r = true; + e = (e) ? e : window.event; + for(var i = element[listener + '_num'] -1; i >= 0; i--) + { + if(element[listener + i](e) == false) + r = false; + } + return r; + } + } + + //if handler is not already stored, assign it + for(var i = 0; i < element[listener + '_num']; i++) + if(element[listener + i] == handler) + return; + element[listener + element[listener + '_num']] = handler; + element[listener + '_num']++; +}; + +floatingMenu.init = function() +{ + floatingMenu.initSecondary(); + floatingMenu.doFloat(); +}; + +// Some browsers init scrollbars only after +// full document load. +floatingMenu.initSecondary = function() +{ + floatingMenu.computeShifts(); + floatingMenu.nextX = floatingMenu.calculateCornerX(); + floatingMenu.nextY = floatingMenu.calculateCornerY(); + floatingMenu.move(); +} + +if (document.layers) + floatingMenu.addEvent(window, 'onload', floatingMenu.init); +else +{ + floatingMenu.init(); + floatingMenu.addEvent(window, 'onload', + floatingMenu.initSecondary); +} \ No newline at end of file diff --git a/Open-ILS/web/js/ui/kcls/circ/selfcheck/payment.js b/Open-ILS/web/js/ui/kcls/circ/selfcheck/payment.js new file mode 100644 index 0000000000..a08d0aedb5 --- /dev/null +++ b/Open-ILS/web/js/ui/kcls/circ/selfcheck/payment.js @@ -0,0 +1,120 @@ +function PaymentForm() {} +var proto = (typeof(SelfCheckManager) == "undefined" ? + PaymentForm : SelfCheckManager).prototype; + +proto.drawPayFinesPage = function(patron, total, xacts, onPaymentSubmit) { + if (typeof(this.authtoken) == "undefined") + this.authtoken = patron.session; + + dojo.query("span", "oils-selfck-cc-payment-summary")[0].innerHTML = total; + + var d = new Date().getFullYear(); + oilsSelfckCCNumber.attr('value', ''); + oilsSelfckCCCVV.attr('value', ''); + oilsSelfckCCMonth.attr('value', '01'); + oilsSelfckCCYear.attr('value', d); + oilsSelfckCCFName.attr('value', patron.first_given_name()); + oilsSelfckCCLName.attr('value', patron.family_name()); + oilsSelfckCCYear.constraints.min=d; + oilsSelfckCCYear.constraints.max=d+10; + + var addr = patron.billing_address() || patron.mailing_address(); + + if (typeof(addr) != "object") { + /* still don't have usable address? try getting better user object. */ + fieldmapper.standardRequest( + ["open-ils.actor", "open-ils.actor.user.fleshed.retrieve"], { + "params": [ + patron.session, patron.id(), [ + "billing_address", "mailing_address" + ] + ], + "async": false, + "oncomplete": function(r) { + var usr = openils.Util.readResponse(r); + if (usr) + addr = usr.billing_address() || usr.mailing_address(); + } + } + ); + } + + if (addr) { + oilsSelfckCCStreet.attr('value', addr.street1()+' '+addr.street2()); + oilsSelfckCCCity.attr('value', addr.city()); + oilsSelfckCCState.attr('value', addr.state()); + oilsSelfckCCZip.attr('value', addr.post_code()); + } + + dojo.connect(oilsSelfckEditDetails, 'onChange', + function(newVal) { + dojo.forEach( + [ oilsSelfckCCFName, + oilsSelfckCCLName, + oilsSelfckCCStreet, + oilsSelfckCCCity, + oilsSelfckCCState, + oilsSelfckCCZip + ], + function(dij) { dij.attr('disabled', !newVal); } + ); + } + ); + + + var self = this; + dojo.connect(oilsSelfckCCSubmit, 'onClick', + function() { + /* XXX better to replace this check on progressDialog with some + * kind of passed-in function to support different use cases */ + if (typeof(progressDialog) != "undefined") + progressDialog.show(true); + + self.sendCCPayment(patron, xacts, onPaymentSubmit); + } + ); +} + +// In this form, this code only supports global on/off credit card +// payments and does not dissallow payments to transactions that started +// at remote locations or transactions that have accumulated billings at +// remote locations that dissalow credit card payments. +// TODO add per-transaction blocks for orgs that do not support CC payments + +proto.sendCCPayment = function(patron, xacts, onPaymentSubmit) { + this.keepMeLoggedIn(); + var args = { + userid : patron.id(), + payment_type : 'credit_card_payment', + payments : xacts, + cc_args : { + where_process : 1, + //type : 'MasterCard',//oilsSelfckCCType.attr('value'), + number : oilsSelfckCCNumber.attr('value'), + cvv2 : oilsSelfckCCCVV.attr('value'), + expire_year : oilsSelfckCCYear.attr('value'), + expire_month : oilsSelfckCCMonth.attr('value'), + billing_first : oilsSelfckCCFName.attr('value'), + billing_last : oilsSelfckCCLName.attr('value'), + billing_address : oilsSelfckCCStreet.attr('value'), + billing_city : oilsSelfckCCCity.attr('value'), + billing_state : oilsSelfckCCState.attr('value'), + billing_zip : oilsSelfckCCZip.attr('value') + } + } + + var resp = fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.money.payment'], + {params : [this.authtoken, args, patron.last_xact_id()]} + ); + + if (typeof(progressDialog) != "undefined") + progressDialog.hide(); + + if (typeof(onPaymentSubmit) == "function") { + onPaymentSubmit(resp); + } else { + var evt = openils.Event.parse(resp); + if (evt) alert(evt); + } +} diff --git a/Open-ILS/web/js/ui/kcls/circ/selfcheck/selfcheck.js b/Open-ILS/web/js/ui/kcls/circ/selfcheck/selfcheck.js new file mode 100644 index 0000000000..0859ec14b1 --- /dev/null +++ b/Open-ILS/web/js/ui/kcls/circ/selfcheck/selfcheck.js @@ -0,0 +1,1488 @@ +dojo.require('dojo.date.locale'); +dojo.require('dojo.date.stamp'); +dojo.require('dijit.form.CheckBox'); +dojo.require('dijit.form.NumberSpinner'); +dojo.require('openils.CGI'); +dojo.require('openils.Util'); +dojo.require('openils.User'); +dojo.require('openils.Event'); +dojo.require('openils.widget.ProgressDialog'); +dojo.require('openils.widget.OrgUnitFilteringSelect'); + +dojo.requireLocalization('openils.circ', 'selfcheck'); +var localeStrings = dojo.i18n.getLocalization('openils.circ', 'selfcheck'); +var selfCheckMgr; +var itemsOutCirc = []; +var itemsOutMod = []; +var itemsOutCopy = []; +var TIMEOUT = 45; // logout timer + + +const SET_BARCODE_REGEX = 'opac.barcode_regex'; +const SET_PATRON_TIMEOUT = 'circ.selfcheck.patron_login_timeout'; +const SET_AUTO_OVERRIDE_EVENTS = 'circ.selfcheck.auto_override_checkout_events'; +const SET_PATRON_PASSWORD_REQUIRED = 'circ.selfcheck.patron_password_required'; +const SET_AUTO_RENEW_INTERVAL = 'circ.checkout_auto_renew_age'; +const SET_WORKSTATION_REQUIRED = 'circ.selfcheck.workstation_required'; +const SET_ALERT_POPUP = 'circ.selfcheck.alert.popup'; +const SET_ALERT_SOUND = 'circ.selfcheck.alert.sound'; +const SET_CC_PAYMENT_ALLOWED = 'credit.payments.allow'; +// This setting only comes into play if COPY_NOT_AVAILABLE is in the SET_AUTO_OVERRIDE_EVENTS list +const SET_BLOCK_CHECKOUT_ON_COPY_STATUS = 'circ.selfcheck.block_checkout_on_copy_status'; + +function SelfCheckManager() { + selfCheckMgr = this; + switchTo('step1'); + + this.timer = null; + this.cgi = new openils.CGI(); + this.staff = null; + this.workstation = null; + this.authtoken = null; + + this.patron = null; + this.patronBarcodeRegex = null; + + this.checkouts = []; + this.itemsOut = []; + + // During renewals, keep track of the ID of the previous circulation. + // Previous circ is used for tracking failed renewals (for receipts). + this.prevCirc = null; + + // current item barcode + this.itemBarcode = null; + + // are we currently performing a renewal? + this.isRenewal = false; + + // dict of org unit settings for "here" + this.orgSettings = {}; + + // Construct a mock checkout for debugging purposes + if(this.mockCheckouts = this.cgi.param('mock-circ')) { + + this.mockCheckout = { + payload : { + record : new fieldmapper.mvr(), + copy : new fieldmapper.acp(), + circ : new fieldmapper.circ() + } + }; + + this.mockCheckout.payload.record.title('Jazz improvisation for guitar'); + this.mockCheckout.payload.record.author('Wise, Les'); + this.mockCheckout.payload.record.isbn('0634033565'); + this.mockCheckout.payload.copy.barcode('123456789'); + this.mockCheckout.payload.circ.renewal_remaining(1); + this.mockCheckout.payload.circ.parent_circ(1); + this.mockCheckout.payload.circ.due_date('2012-12-21'); + } + + this.initPrinter(); +} + +SelfCheckManager.prototype.keepMeLoggedIn = function() { + //alert(this.timer); + if(this.timer) try {clearTimeout(this.timer)} catch(e){} + this.timer = setTimeout('selfCheckMgr.logoutPatron();', TIMEOUT*1000); +} + +/** + * Fetch the org-unit settings, initialize the display, etc. + */ +SelfCheckManager.prototype.init = function() { + this.staff = openils.User.user; + this.workstation = openils.User.workstation; + this.authtoken = openils.User.authtoken; + this.loadOrgSettings(); + + this.circTbody = dojo.byId('oils-selfck-circ-tbody'); + this.itemsOutTbody = dojo.byId('oils-selfck-circ-out-tbody'); + + // workstation is required but none provided + if(this.orgSettings[SET_WORKSTATION_REQUIRED] && !this.workstation) { + if(confirm(dojo.string.substitute(localeStrings.WORKSTATION_REQUIRED))) { + this.registerWorkstation(); + } + return; + } + + var self = this; + // connect onclick handlers to the various navigation links + var linkHandlers = { + 'oils-selfck-hold-details-link' : function() { self.drawHoldsPage(true); }, + 'oils-selfck-view-fines-link' : function() { self.drawFinesPage(); openils.Util.show('oils-selfck-fines-tbody'); openils.Util.hide('pay_fines'); }, + 'oils-selfck-pay-fines-link' : function() { + switchTo('step3','step3c'); + openils.Util.hide('oils-selfck-fines-tbody'); + openils.Util.show('pay_fines'); + self.keepMeLoggedIn(); + self.drawPayFinesPage( + self.patron, + self.getSelectedFinesTotal(), + self.getSelectedFineTransactions(), + function(resp) { + var evt = openils.Event.parse(resp); + if(evt) { + var message = evt + ''; + if(evt.textcode == 'CREDIT_PROCESSOR_DECLINED_TRANSACTION' && evt.payload) + message += '\n' + evt.payload.error_message; + self.handleAlert(message, true, 'payment-failure'); + return; + } + self.patron.last_xact_id(resp.last_xact_id); + self.printPaymentReceipt( + resp, + function() { + self.updateFinesSummary(); + self.drawFinesPage(); + } + ); + } + ); + }, + //'oils-selfck-nav-home' : function() { self.drawCircPage(); }, + 'oils-selfck-nav-logout' : function() { self.logoutPatron(); }, + 'oils-selfck-nav-logout-print' : function() { self.logoutPatron(true); }, + 'oils-selfck-items-out-details-link' : function() { self.drawItemsOutPage(); }, + //'oils-selfck-print-list-link' : function() { self.printList(); } + } + + for(var id in linkHandlers) { + //var obj1 = dojo.byId(id); + //obj1.onclick = linkHandlers[id]; + dojo.connect(dojo.byId(id), 'onclick', linkHandlers[id]); + } + + + if(this.cgi.param('patron')) { + + // Patron barcode via cgi param. Mainly used for debugging and + // only works if password is not required by policy + this.loginPatron(this.cgi.param('patron')); + + } else { + this.drawLoginPage(); + } + + /** + * To test printing, pass a URL param of 'testprint'. The value for the param + * should be a JSON string like so: [{circ:}, ...] + */ + var testPrint = this.cgi.param('testprint'); + if(testPrint) { + this.checkouts = JSON2js(testPrint); + this.printSessionReceipt(); + this.checkouts = []; + } +} + + +SelfCheckManager.prototype.getSelectedFinesTotal = function() { + var total = 0; + dojo.forEach( + dojo.query("[name=selector]", this.finesTbody), + function(input) { + if(input.checked) + total += Number(input.balance_owed); + } + ); + return total.toFixed(2); +}; + +SelfCheckManager.prototype.getSelectedFineTransactions = function() { + return dojo.query("[name=selector]", this.finesTbody). + filter(function (o) { return o.checked }). + map( + function (o) { + return [ + o.getAttribute("xact"), + Number(o.balance_owed).toFixed(2) + ]; + } + ); +}; + +/** + * Registers a new workstion + */ +SelfCheckManager.prototype.registerWorkstation = function() { + + oilsSelfckWsDialog.show(); + + new openils.User().buildPermOrgSelector( + 'REGISTER_WORKSTATION', + oilsSelfckWsLocSelector, + this.staff.home_ou() + ); + + + var self = this; + dojo.connect(oilsSelfckWsSubmit, 'onClick', + + function() { + oilsSelfckWsDialog.hide(); + var name = oilsSelfckWsLocSelector.attr('displayedValue') + '-' + oilsSelfckWsName.attr('value'); + + var res = fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.workstation.register'], + { params : [ + self.authtoken, name, oilsSelfckWsLocSelector.attr('value') + ] + } + ); + + if(evt = openils.Event.parse(res)) { + if(evt.textcode == 'WORKSTATION_NAME_EXISTS') { + if(confirm(localeStrings.WORKSTATION_EXISTS)) { + location.href = location.href.replace(/\?.*/, '') + '?ws=' + name; + } else { + self.registerWorkstation(); + } + return; + } else { + alert(evt); + } + } else { + location.href = location.href.replace(/\?.*/, '') + '?ws=' + name; + } + } + ); +} + +/** + * Loads the org unit settings + */ +SelfCheckManager.prototype.loadOrgSettings = function() { + + var settings = fieldmapper.aou.fetchOrgSettingBatch( + this.staff.ws_ou(), [ + SET_BARCODE_REGEX, + SET_PATRON_TIMEOUT, + SET_ALERT_POPUP, + SET_ALERT_SOUND, + SET_AUTO_OVERRIDE_EVENTS, + SET_BLOCK_CHECKOUT_ON_COPY_STATUS, + SET_PATRON_PASSWORD_REQUIRED, + SET_AUTO_RENEW_INTERVAL, + SET_WORKSTATION_REQUIRED, + SET_CC_PAYMENT_ALLOWED + ] + ); + + for(k in settings) { + if(settings[k]) + this.orgSettings[k] = settings[k].value; + } + + if(settings[SET_BARCODE_REGEX]) + this.patronBarcodeRegex = new RegExp(settings[SET_BARCODE_REGEX].value); +} + +SelfCheckManager.prototype.drawLoginPage = function() { + var self = this; + var bcHandler = function(barcode) { + // handle patron barcode entry + + if(self.orgSettings[SET_PATRON_PASSWORD_REQUIRED]) { + + // password is required. wire up the scan box to read it + self.updateScanBox({ + msg : 'Please enter your password', // TODO i18n + handler : function(pw) { self.loginPatron(barcode, pw); }, + password : true + }); + + } else { + // password is not required, go ahead and login + self.loginPatron(barcode); + } + }; + + this.updateScanBox({ + msg : 'Please log in with your library barcode.', // TODO + handler : bcHandler + }); + + var txtBox = (dojo.byId('step2').style.display=='none') ? 'patron-login-username' : 'patron-login-password'; + try{var a=dojo.byId(txtBox);a.focus();a.select();}catch(e){} +} + +/** + * Login the patron. + */ +SelfCheckManager.prototype.loginPatron = function(barcode, passwd) { + + //if(this.orgSettings[SET_PATRON_PASSWORD_REQUIRED]) { // password always reqired, per KCLS - fail safe + if(!passwd) { + // would only happen in dev/debug mode when using the patron= param + alert('password required by org setting. remove patron= from URL'); + return; + } + + // patron password is required. Verify it. + + var res = fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.verify_user_password'], + {params : [this.authtoken, barcode, null, hex_md5(passwd)]} + ); + + if(res == 0) { + // user-not-found results in login failure + this.handleAlert( + dojo.string.substitute(localeStrings.LOGIN_FAILED, [barcode]), + false, 'login-failure' + ); + this.drawLoginPage(); + openils.Util.show('back_to_login'); + return; + } + //} + + // retrieve the fleshed user by barcode + this.patron = fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.user.fleshed.retrieve_by_barcode'], + {params : [this.authtoken, barcode]} + ); + + var evt = openils.Event.parse(this.patron); + if(evt) { + this.handleAlert( + dojo.string.substitute(localeStrings.LOGIN_FAILED, [barcode]), + false, 'login-failure' + ); + this.drawLoginPage(); + openils.Util.show('back_to_login'); + + } else { + + //this.handleAlert('', true, 'login-success'); + dojo.byId('user_name').innerHTML = + dojo.string.substitute(localeStrings.WELCOME_BANNER, [this.patron.first_given_name()]); + dojo.byId('oils-selfck-status-div').innerHTML = ''; + dojo.byId('oils-selfck-status-div2').innerHTML = ''; + dojo.byId('oils-selfck-status-div3').innerHTML = ''; + openils.Util.hide('back_to_login'); + this.drawCircPage(); + } +} + + +SelfCheckManager.prototype.handleAlert = function(message, shouldPopup, sound) { + console.log("Handling alert " + message); + + dojo.byId('oils-selfck-status-div').innerHTML = message; + if(!this.patron){ + dojo.byId('oils-selfck-status-div2').innerHTML = message; + dojo.byId('oils-selfck-status-div3').innerHTML = message; + } + + if(shouldPopup && this.orgSettings[SET_ALERT_POPUP]) + alert(message); + + if(this.orgSettings[SET_ALERT_SOUND]) + openils.Util.playAudioUrl(SelfCheckManager.audioConfig[sound]); +} + + +/** + * Manages the main input box + * @param msg The context message to display with the box + * @param clearOnly Don't update the context message, just clear the value and re-focus + * @param handler Optional "on-enter" handler. + */ +SelfCheckManager.prototype.updateScanBox = function(args) { + args = args || {}; + + if(args.select) { + selfckScanBox.domNode.select(); + } else { + selfckScanBox.attr('value', ''); + } + + if(args.password) { + selfckScanBox.domNode.setAttribute('type', 'password'); + } else { + selfckScanBox.domNode.setAttribute('type', ''); + } + + if(args.value) + selfckScanBox.attr('value', args.value); + + if(args.msg) + dojo.byId('oils-selfck-scan-text').innerHTML = args.msg; + + if(selfckScanBox._lastHandler && (args.handler || args.clearHandler)) { + dojo.disconnect(selfckScanBox._lastHandler); + } + + if(args.handler) { + + selfckScanBox._lastHandler = dojo.connect( + selfckScanBox, + 'onKeyDown', + function(e) { + if(e.keyCode != dojo.keys.ENTER) + return; + args.handler(selfckScanBox.attr('value')); + } + ); + } + + selfckScanBox.focus(); +} + +/** + * Sets up the checkout/renewal interface + */ +SelfCheckManager.prototype.drawCircPage = function() { + this.keepMeLoggedIn(); + openils.Util.show('oils-selfck-circ-tbody', 'table-row-group'); + switchTo('step3'); + + var self = this; + this.updateScanBox({ + msg : 'Please enter an item barcode', // TODO i18n + handler : function(barcode) { + openils.Util.show('oils-selfck-fines-tbody'); + openils.Util.hide('pay_fines'); switchTo('step3'); + self.checkout(barcode); } + }); + + if(!this.circTemplate) + this.circTemplate = this.circTbody.removeChild(dojo.byId('oils-selfck-circ-row')); + + // fines summary + this.updateFinesSummary(); + + // holds summary + this.updateHoldsSummary(); + + // items out summary + this.updateCircSummary(); + + // render mock checkouts for debugging? + if(this.mockCheckouts) { + for(var i in [1,2,3]) + this.displayCheckout(this.mockCheckout, 'checkout'); + } +} + + +SelfCheckManager.prototype.updateFinesSummary = function() { + var self = this; + + // fines summary + fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.user.fines.summary'], + { async : true, + params : [this.authtoken, this.patron.id()], + oncomplete : function(r) { + var summary = openils.Util.readResponse(r); + var finesSum = dojo.byId('acct_fines'); + var bal = summary.balance_owed(); + var bal2 = parseFloat(bal); + + if(bal2>0) {finesSum.style.color="red"; openils.Util.show('oils-selfck-pay-fines-link');} + finesSum.innerHTML = dojo.string.substitute(localeStrings.TOTAL_FINES_ACCOUNT, [bal2.toFixed(2)]); + self.creditPayableBalance = bal2+''; + } + } + ); +} + + +SelfCheckManager.prototype.drawItemsOutPage = function() { + this.keepMeLoggedIn(); + switchTo('step3','step3d'); + + if(!this.outTemplate) + this.outTemplate = this.itemsOutTbody.removeChild(dojo.byId('oils-selfck-circ-out-row')); + while(this.itemsOutTbody.childNodes[0]) + this.itemsOutTbody.removeChild(this.itemsOutTbody.childNodes[0]); + + progressDialog.show(true); + var self = this; + + fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.actor.user.checked_out.atomic'], + { + async : true, + params : [this.authtoken, this.patron.id()], + oncomplete : function(r) { + var resp = openils.Util.readResponse(r); + + var circs = resp.sort( + function(a, b) { + if(a.circ.due_date() > b.circ.due_date()) + return -1; + return 1; + } + ); + + self.itemsOut = []; + dojo.forEach(circs, + function(circ) { + self.itemsOut.push(circ.circ.id()); + handleCheckedItems(circ); + } + ); + progressDialog.hide(); + } + } + ); +} + +function handleCheckedItems(circ) { + var self = selfCheckMgr; + var row = self.outTemplate.cloneNode(true); + + self.byName(row,'barcode').innerHTML = circ.copy.barcode(); + self.byName(row,'title').innerHTML = circ.record.title(); + self.byName(row,'author').innerHTML = circ.record.author(); + if(dojo.date.stamp.fromISOString(circ.circ.due_date())<(new Date())) self.byName(row,'due_date').style.color="red"; + self.byName(row,'due_date').innerHTML = dojo.date.locale.format(dojo.date.stamp.fromISOString(circ.circ.due_date()), {selector: 'date', fullYear: true}); + self.byName(row,'format').innerHTML = circ.record.types_of_resource()[0]; + + self.itemsOutTbody.appendChild(row); +} + +SelfCheckManager.prototype.goToTab = function(name) { + this.tabName = name; + + openils.Util.hide('oils-selfck-fines-page'); + openils.Util.hide('oils-selfck-payment-page'); + openils.Util.hide('oils-selfck-holds-page'); + openils.Util.hide('oils-selfck-circ-page'); + openils.Util.hide('oils-selfck-pay-fines-link'); + + switch(name) { + case 'checkout': + openils.Util.show('oils-selfck-circ-page'); + break; + case 'items_out': + openils.Util.show('oils-selfck-circ-page'); + break; + case 'holds': + openils.Util.show('oils-selfck-holds-page'); + break; + case 'fines': + openils.Util.show('oils-selfck-fines-page'); + break; + case 'payment': + openils.Util.show('oils-selfck-payment-page'); + break; + } +} + + +SelfCheckManager.prototype.printList = function(which) { + this.keepMeLoggedIn(); + switch(which) { + case 'checkout': + this.printSessionReceipt(); + break; + case 'items_out': + this.printItemsOutReceipt(); + break; + case 'holds': + this.printHoldsReceipt(); + break; + case 'fines': + this.printFinesReceipt(); + break; + } +} + +SelfCheckManager.prototype.updateHoldsSummary = function() { + if(!this.holdsSummary) { + var summary = fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.holds.user_summary'], + {params : [this.authtoken, this.patron.id()]} + ); + + this.holdsSummary = {}; + this.holdsSummary.ready = Number(summary['4']); + this.holdsSummary.total = 0; + + for(var i in summary) + this.holdsSummary.total += Number(summary[i]); + } + + dojo.byId('oils-selfck-holds-total').innerHTML =dojo.string.substitute("${0}) Item"+(this.holdsSummary.total==1?"":"s"),[this.holdsSummary.total]); + dojo.byId('oils-selfck-holds-ready').innerHTML =dojo.string.substitute("${0}) Item"+(this.holdsSummary.ready==1?"":"s"),[this.holdsSummary.ready]); +} + + +SelfCheckManager.prototype.updateCircSummary = function(increment) { + if(!this.circSummary) { + + var summary = fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.user.checked_out.count'], + {params : [this.authtoken, this.patron.id()]} + ); + + this.circSummary = { + total : Number(summary.out) + Number(summary.overdue), + overdue : Number(summary.overdue), + session : 0 + }; + } + + if(increment) { + // local checkout occurred. Add to the total and the session. + this.circSummary.total += 1; + this.circSummary.session += 1; + } + + dojo.byId('oils-selfck-circ-account-total').innerHTML = dojo.string.substitute("${0}) Item"+(this.circSummary.total==1?"":"s"), [this.circSummary.total]); + + /* + dojo.byId('oils-selfck-circ-session-total').innerHTML = + dojo.string.substitute( + localeStrings.TOTAL_ITEMS_SESSION, + [this.circSummary.session] + ); + */ +} + + +SelfCheckManager.prototype.drawHoldsPage = function(bool) { + this.keepMeLoggedIn(); + if(bool) switchTo('step3','step3f'); else switchTo('step3','step3e'); + + this.holdTbody = dojo.byId('oils-selfck-hold-tbody'); + this.readyTbody = dojo.byId('oils-selfck-rdy-tbody'); + if(!this.readyTemplate) + this.readyTemplate = this.readyTbody.removeChild(dojo.byId('oils-selfck-rdy-row')); + if(!this.holdTemplate) + this.holdTemplate = this.holdTbody.removeChild(dojo.byId('oils-selfck-hold-row')); + while(this.holdTbody.childNodes[0]) + this.holdTbody.removeChild(this.holdTbody.childNodes[0]); + while(this.readyTbody.childNodes[0]) + this.readyTbody.removeChild(this.readyTbody.childNodes[0]); + + progressDialog.show(true); + + var self = this; + fieldmapper.standardRequest( // fetch the hold IDs + + ['open-ils.circ', 'open-ils.circ.holds.id_list.retrieve'], + { async : true, + params : [this.authtoken, this.patron.id()], + + oncomplete : function(r) { + var ids = openils.Util.readResponse(r); + if(!ids || ids.length == 0) { + progressDialog.hide(); + return; + } + + fieldmapper.standardRequest( // fetch the hold objects with fleshed details + ['open-ils.circ', 'open-ils.circ.hold.details.batch.retrieve'], + { async : true, + params : [self.authtoken, ids], + + onresponse : function(rr) { + progressDialog.hide(); + self.drawHolds(openils.Util.readResponse(rr)); + } + } + ); + } + } + ); +} + +/** + * Fetch and add a single hold to the list of holds + */ +SelfCheckManager.prototype.drawHolds = function(holds) { + //this.keepMeLoggedIn(); + this.holds = holds; + progressDialog.hide(); + + var data = holds; + if(!data) return; + var row = this.holdTemplate.cloneNode(true); + var row2 = this.readyTemplate.cloneNode(true); + + //if(data.mvr.isbn()) { + // this.byName(row, 'jacket').setAttribute('src', '/opac/extras/ac/jacket/small/' + data.mvr.isbn()); + //} + + if(data.status == 4) { + this.byName(row2, 'title').innerHTML = data.mvr.title(); + this.byName(row2, 'format').innerHTML = data.mvr.types_of_resource()[0]; + this.byName(row2, 'lib').innerHTML = fieldmapper.aou.findOrgUnit(data.hold.pickup_lib()).name(); + if(dojo.date.stamp.fromISOString(data.hold.capture_time())<(new Date())) this.byName(row2, 'date').style.color="red"; + this.byName(row2, 'date').innerHTML = dojo.date.locale.format(dojo.date.stamp.fromISOString(data.hold.capture_time()), {selector: 'date', fullYear: true}); + this.readyTbody.appendChild(row2); + } else { + + this.byName(row, 'title').innerHTML = data.mvr.title(); + this.byName(row, 'author').innerHTML = data.mvr.author(); + this.byName(row, 'format').innerHTML = data.mvr.types_of_resource()[0]; + + // hold is still pending + this.byName(row, 'status').innerHTML = dojo.string.substitute(localeStrings.HOLD_STATUS_WAITING,[data.queue_position, data.potential_copies]); + this.holdTbody.appendChild(row); + } +} + + +SelfCheckManager.prototype.drawFinesPage = function() { + this.keepMeLoggedIn(); + // TODO add option to hid scanBox + // this.updateScanBox(...) + + //this.goToTab('fines'); + switchTo('step3','step3c'); + progressDialog.show(true); + + //if(this.creditPayableBalance > 0 && this.orgSettings[SET_CC_PAYMENT_ALLOWED]) + // openils.Util.show('oils-selfck-pay-fines-link', 'inline'); + + + this.finesTbody = dojo.byId('oils-selfck-fines-tbody'); + if(!this.finesTemplate) + this.finesTemplate = this.finesTbody.removeChild(dojo.byId('oils-selfck-fines-row')); + while(this.finesTbody.childNodes[0]) + this.finesTbody.removeChild(this.finesTbody.childNodes[0]); + +/* + // when user clicks on a selector checkbox, update the total owed + var updateSelected = function() { + var total = 0; + dojo.forEach( + dojo.query('[name=selector]', this.finesTbody), + function(input) { + if(input.checked) + total += Number(input.getAttribute('balance_owed')); + } + ); + + total = total.toFixed(2); + dojo.byId('oils-selfck-selected-total').innerHTML = + dojo.string.substitute(localeStrings.TOTAL_FINES_SELECTED, [total]); + } + + // wire up the batch on/off selector + var sel = dojo.byId('oils-selfck-fines-selector'); + sel.onchange = function() { + dojo.forEach( + dojo.query('[name=selector]', this.finesTbody), + function(input) { + input.checked = sel.checked; + } + ); + }; +*/ + var self = this; + var handler = function(dataList) { + + self.finesCount = dataList.length; + self.finesData = dataList; + + for(var i in dataList) { + + var data = dataList[i]; + var row = self.finesTemplate.cloneNode(true); + var type = data.transaction.xact_type(); + + if(type == 'circulation') { + self.byName(row, 'title').innerHTML = data.record.title(); + if(dojo.date.stamp.fromISOString(data.circ.due_date())<(new Date())) self.byName(row, 'due_date').style.color="red"; + self.byName(row, 'due_date').innerHTML = dojo.date.locale.format(dojo.date.stamp.fromISOString(data.circ.due_date()), {selector: 'date', fullYear: true}); + self.byName(row, 'date_return').innerHTML = (data.circ.checkin_time())?dojo.date.locale.format(dojo.date.stamp.fromISOString(data.circ.checkin_time()), {selector: 'date', fullYear: true}):""; + + } else if(type == 'grocery') { + self.byName(row, 'title').innerHTML = (data.transaction.last_billing_type())?("Miscellaneous - "+data.transaction.last_billing_type()):"Miscellaneous"; // Go ahead and head off any confusion around "grocery". TODO i18n + } + + //self.byName(row, 'total_owed').innerHTML = data.transaction.total_owed(); + //self.byName(row, 'total_paid').innerHTML = data.transaction.total_paid(); + self.byName(row, 'balance').innerHTML = data.transaction.balance_owed(); + self.byName(row, 'selector').balance_owed = data.transaction.balance_owed(); + self.byName(row, 'selector').setAttribute('xact', data.transaction.id()); +/* + // row selector + var selector = self.byName(row, 'selector') + selector.onchange = updateSelected; + selector.setAttribute('xact', data.transaction.id()); + selector.setAttribute('balance_owed', data.transaction.balance_owed()); + selector.checked = true; +*/ + self.finesTbody.appendChild(row); + } + + //updateSelected(); + } + + + fieldmapper.standardRequest( + ['open-ils.actor', 'open-ils.actor.user.transactions.have_balance.fleshed'], + { async : true, + params : [this.authtoken, this.patron.id()], + oncomplete : function(r) { + progressDialog.hide(); + handler(openils.Util.readResponse(r)); + } + } + ); +} + +SelfCheckManager.prototype.checkin = function(barcode, abortTransit) { + var resp = fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.transit.abort'], + {params : [this.authtoken, {barcode : barcode}]} + ); + + // resp == 1 on success + if(openils.Event.parse(resp)) + return false; + + var resp = fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.checkin.override'], + {params : [ + this.authtoken, { + patron_id : this.patron.id(), + copy_barcode : barcode, + noop : true + } + ]} + ); + + if(!resp.length) resp = [resp]; + for(var i = 0; i < resp.length; i++) { + var tc = openils.Event.parse(resp[i]).textcode; + if(tc == 'SUCCESS' || tc == 'NO_CHANGE') { + continue; + } else { + return false; + } + } + + return true; +} + +/** + * Check out a single item. If the item is already checked + * out to the patron, redirect to renew() + */ +SelfCheckManager.prototype.checkout = function(barcode, override) { + this.keepMeLoggedIn(); + this.prevCirc = null; + + if(!barcode) { + this.updateScanbox(null, true); + return; + } + + if(this.mockCheckouts) { + // if we're in mock-checkout mode, just insert another + // fake circ into the table and get out of here. + this.displayCheckout(this.mockCheckout, 'checkout'); + return; + } + + // TODO see if it's a patron barcode + // TODO see if this item has already been checked out in this session + + var method = 'open-ils.circ.checkout.full'; + if(override) method += '.override'; + + console.log("Checkout out item " + barcode + " with method " + method); + + var result = fieldmapper.standardRequest( + ['open-ils.circ', method], + {params: [ + this.authtoken, { + patron_id : this.patron.id(), + copy_barcode : barcode + } + ]} + ); + + var stat = this.handleXactResult('checkout', barcode, result); + + if(stat.override) { + this.checkout(barcode, true); + } else if(stat.doOver) { + this.checkout(barcode); + } else if(stat.renew) { + this.renew(barcode); + } +} + +SelfCheckManager.prototype.failPartMessage = function(result) { + if (result.payload && result.payload.fail_part) { + var stringKey = "FAIL_PART_" + + result.payload.fail_part.replace(/\./g, "_"); + return localeStrings[stringKey]; + } else { + return null; + } +} + +SelfCheckManager.prototype.handleXactResult = function(action, item, result) { + var displayText = ''; + + // If true, the display message is important enough to pop up. Whether or not + // an alert() actually occurs, depends on org unit settings + var popup = false; + var sound = ''; // sound file reference + var payload = result.payload || {}; + var overrideEvents = this.orgSettings[SET_AUTO_OVERRIDE_EVENTS]; + var blockStatuses = this.orgSettings[SET_BLOCK_CHECKOUT_ON_COPY_STATUS]; + result.payload = payload; + + if(result.textcode == 'NO_SESSION') { + + return this.logoutStaff(); + + } else if(result.textcode == 'SUCCESS') { + + if(action == 'checkout') { + + displayText = dojo.string.substitute(localeStrings.CHECKOUT_SUCCESS, [item]); + this.displayCheckout(result, 'checkout'); + + if(payload.holds_fulfilled && payload.holds_fulfilled.length) { + // A hold was fulfilled, update the hold numbers in the circ summary + console.log("fulfilled hold " + payload.holds_fulfilled + " during checkout"); + this.holdsSummary = null; + this.updateHoldsSummary(); + } + + this.updateCircSummary(true); + + } else if(action == 'renew') { + + displayText = dojo.string.substitute(localeStrings.RENEW_SUCCESS, [item]); + this.displayCheckout(result, 'renew'); + } + + this.checkouts.push({circ : result.payload.circ.id()}); + sound = 'checkout-success'; + this.updateScanBox(); + + } else if(result.textcode == 'OPEN_CIRCULATION_EXISTS' && action == 'checkout') { + + // Server says the item is already checked out. If it's checked out to the + // current user, we may need to renew it. + + if(payload.old_circ) { + + /* + old_circ refers to the previous checkout IFF it's for the same user. + If no auto-renew interval is not defined, assume we should renew it + If an auto-renew interval is defined and the payload comes back with + auto_renew set to true, do the renewal. Otherwise, let the patron know + the item is already checked out to them. */ + + if( !this.orgSettings[SET_AUTO_RENEW_INTERVAL] || + (this.orgSettings[SET_AUTO_RENEW_INTERVAL] && payload.auto_renew) ) { + this.prevCirc = payload.old_circ.id(); + return { renew : true }; + } + + popup = false; + sound = 'checkout-failure'; + displayText = dojo.string.substitute(localeStrings.ALREADY_OUT, [item]); + + } else { + + if( // copy is marked lost. if configured to do so, check it in and try again. + result.payload.copy && + result.payload.copy.status() == /* LOST */ 3 && + overrideEvents && overrideEvents.length && + overrideEvents.indexOf('COPY_STATUS_LOST') != -1) { + + if(this.checkin(item)) { + return { doOver : true }; + } + } + + + // item is checked out to some other user + popup = false; + sound = 'checkout-failure'; + displayText = dojo.string.substitute(localeStrings.OPEN_CIRCULATION_EXISTS, [item]); + } + + this.updateScanBox(); + + } else { + + + if(overrideEvents && overrideEvents.length) { + + // see if the events we received are all in the list of + // events to override + + if(!result.length) result = [result]; + + var override = true; + for(var i = 0; i < result.length; i++) { + + var match = overrideEvents.filter(function(e) { return (e == result[i].textcode); })[0]; + + if(!match) { + override = false; + break; + } + + if(result[i].textcode == 'COPY_NOT_AVAILABLE' && blockStatuses && blockStatuses.length) { + + var stat = result[i].payload.status(); // copy status + if(typeof stat == 'object') stat = stat.id(); + + var match2 = blockStatuses.filter(function(e) { return (e == stat); })[0]; + + if(match2) { // copy is in a blocked status + override = false; + break; + } + } + + if(result[i].textcode == 'COPY_IN_TRANSIT') { + // to override a transit, we have to abort the transit and check it in first + if(this.checkin(item, true)) { + return { doOver : true }; + } else { + override = false; + } + } + } + + if(override) + return { override : true }; + } + + this.updateScanBox(); + popup = false; + sound = 'checkout-failure'; + + if(action == 'renew') + this.checkouts.push({circ : this.prevCirc, renewal_failure : true}); + + if(result.length) + result = result[0]; + + switch(result.textcode) { + + // TODO custom handler for blocking penalties + + case 'MAX_RENEWALS_REACHED' : + displayText = dojo.string.substitute( + localeStrings.MAX_RENEWALS, [item]); + break; + + case 'ITEM_NOT_CATALOGED' : + displayText = dojo.string.substitute( + localeStrings.ITEM_NOT_CATALOGED, [item]); + break; + + case 'OPEN_CIRCULATION_EXISTS' : + displayText = dojo.string.substitute( + localeStrings.OPEN_CIRCULATION_EXISTS, [item]); + + break; + + default: + console.error('Unhandled event ' + result.textcode); + + if (!(displayText = this.failPartMessage(result))) { + if (action == 'checkout' || action == 'renew') { + displayText = dojo.string.substitute( + localeStrings.GENERIC_CIRC_FAILURE, [item]); + } else { + displayText = dojo.string.substitute( + localeStrings.UNKNOWN_ERROR, [result.textcode]); + } + } + } + } + + this.handleAlert(displayText, popup, sound); + return {}; +} + + +/** + * Renew an item + */ +SelfCheckManager.prototype.renew = function(barcode, override) { + + var method = 'open-ils.circ.renew'; + if(override) method += '.override'; + + console.log("Renewing item " + barcode + " with method " + method); + + var result = fieldmapper.standardRequest( + ['open-ils.circ', method], + {params: [ + this.authtoken, { + patron_id : this.patron.id(), + copy_barcode : barcode + } + ]} + ); + + console.log(js2JSON(result)); + + var stat = this.handleXactResult('renew', barcode, result); + + if(stat.override) + this.renew(barcode, true); +} + +/** + * Display the result of a checkout or renewal in the items out table + */ +SelfCheckManager.prototype.displayCheckout = function(evt, type, itemsOut) { + var copy = evt.payload.copy; + var record = evt.payload.record; + var circ = evt.payload.circ; + var row = this.circTemplate.cloneNode(true); + + //if(record.isbn()) { + // this.byName(row, 'jacket').setAttribute('src', '/opac/extras/ac/jacket/small/' + record.isbn()); + //} + + this.byName(row, 'barcode').innerHTML = copy.barcode(); + this.byName(row, 'title').innerHTML = record.title(); + //this.byName(row, 'author').innerHTML = record.author(); + //this.byName(row, 'remaining').innerHTML = circ.renewal_remaining(); + openils.Util.show(this.byName(row, type)); + + var date = dojo.date.stamp.fromISOString(circ.due_date()); + this.byName(row, 'due_date').innerHTML = + dojo.date.locale.format(date, {selector : 'date'}); + + // put new circs at the top of the list + var tbody = this.circTbody; + if(itemsOut) tbody = this.itemsOutTbody; + tbody.insertBefore(row, tbody.getElementsByTagName('tr')[0]); +} + + +SelfCheckManager.prototype.byName = function(node, name) { + return dojo.query('[name=' + name+']', node)[0]; +} + + +SelfCheckManager.prototype.initPrinter = function() { + try { // Mozilla only + netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + netscape.security.PrivilegeManager.enablePrivilege('UniversalPreferencesRead'); + netscape.security.PrivilegeManager.enablePrivilege('UniversalPreferencesWrite'); + var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch); + if (pref) + pref.setBoolPref('print.always_print_silent', true); + } catch(E) { + console.log("Unable to initialize auto-printing"); + } +} + +/** + * Print a receipt for this session's checkouts + */ +SelfCheckManager.prototype.printSessionReceipt = function(callback) { + var circIds = []; + var circCtx = []; // circ context data. in this case, renewal_failure info + + // collect the circs and failure info + dojo.forEach( + this.checkouts, + function(blob) { + circIds.push(blob.circ); + circCtx.push({renewal_failure:blob.renewal_failure}); + } + ); + + var params = [ + this.authtoken, + this.staff.ws_ou(), + null, + 'format.selfcheck.checkout', + 'print-on-demand', + circIds, + circCtx + ]; + + var self = this; + fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.fire_circ_trigger_events'], + { + async : true, + params : params, + oncomplete : function(r) { + var resp = openils.Util.readResponse(r); + var output = resp.template_output(); + if(output) { + self.printData(output.data(), self.checkouts.length, callback); + } else { + var error = resp.error_output(); + if(error) { + throw new Error("Error creating receipt: " + error.data()); + } else { + throw new Error("No receipt data returned from server"); + } + } + } + } + ); +} + +SelfCheckManager.prototype.printData = function(data, numItems, callback) { + var win = window.open('', '', 'resizable,width=350,height=250,scrollbars=1'); + win.document.body.innerHTML = data; + win.print(); + + /* + * There is no way to know when the browser is done printing. + * Make a best guess at when to close the print window by basing + * the setTimeout wait on the number of items to be printed plus + * a small buffer + */ + var sleepTime = 1000; + if(numItems > 0) + sleepTime += (numItems / 2) * 1000; + + setTimeout( + function() { + win.close(); // close the print window + if(callback) callback(); // fire optional post-print callback + }, + sleepTime + ); +} + + +/** + * Print a receipt for this user's items out + */ +SelfCheckManager.prototype.printItemsOutReceipt = function(callback) { + if(!this.itemsOut.length) return; + + progressDialog.show(true); + + var params = [ + this.authtoken, + this.staff.ws_ou(), + null, + 'format.selfcheck.items_out', + 'print-on-demand', + this.itemsOut + ]; + + var self = this; + fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.fire_circ_trigger_events'], + { + async : true, + params : params, + oncomplete : function(r) { + progressDialog.hide(); + var resp = openils.Util.readResponse(r); + var output = resp.template_output(); + if(output) { + self.printData(output.data(), self.itemsOut.length, callback); + } else { + var error = resp.error_output(); + if(error) { + throw new Error("Error creating receipt: " + error.data()); + } else { + throw new Error("No receipt data returned from server"); + } + } + } + } + ); +} + +/** + * Print a receipt for this user's items out + */ +SelfCheckManager.prototype.printHoldsReceipt = function(callback) { + if(!this.holds.length) return; + + progressDialog.show(true); + + var holdIds = []; + var holdData = []; + + dojo.forEach(this.holds, + function(data) { + holdIds.push(data.hold.id()); + if(data.status == 4) { + holdData.push({ready : true}); + } else { + holdData.push({ + queue_position : data.queue_position, + potential_copies : data.potential_copies + }); + } + } + ); + + var params = [ + this.authtoken, + this.staff.ws_ou(), + null, + 'format.selfcheck.holds', + 'print-on-demand', + holdIds, + holdData + ]; + + var self = this; + fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.fire_hold_trigger_events'], + { + async : true, + params : params, + oncomplete : function(r) { + progressDialog.hide(); + var resp = openils.Util.readResponse(r); + var output = resp.template_output(); + if(output) { + self.printData(output.data(), self.holds.length, callback); + } else { + var error = resp.error_output(); + if(error) { + throw new Error("Error creating receipt: " + error.data()); + } else { + throw new Error("No receipt data returned from server"); + } + } + } + } + ); +} + + +SelfCheckManager.prototype.printPaymentReceipt = function(paymentIds, callback) { + var self = this; + progressDialog.show(true); + + fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.money.payment_receipt.print'], + { + async : true, + params : [this.authtoken, paymentIds], + oncomplete : function(r) { + var resp = openils.Util.readResponse(r); + var output = resp.template_output(); + progressDialog.hide(); + if(output) { + self.printData(output.data(), 1, callback); + } else { + var error = resp.error_output(); + if(error) { + throw new Error("Error creating receipt: " + error.data()); + } else { + throw new Error("No receipt data returned from server"); + } + } + } + } + ); +} + +/** + * Print a receipt for this user's items out + */ +SelfCheckManager.prototype.printFinesReceipt = function(callback) { + progressDialog.show(true); + + var params = [ + this.authtoken, + this.staff.ws_ou(), + null, + 'format.selfcheck.fines', + 'print-on-demand', + [this.patron.id()] + ]; + + var self = this; + fieldmapper.standardRequest( + ['open-ils.circ', 'open-ils.circ.fire_user_trigger_events'], + { + async : true, + params : params, + oncomplete : function(r) { + progressDialog.hide(); + var resp = openils.Util.readResponse(r); + var output = resp.template_output(); + if(output) { + self.printData(output.data(), self.finesCount, callback); + } else { + var error = resp.error_output(); + if(error) { + throw new Error("Error creating receipt: " + error.data()); + } else { + throw new Error("No receipt data returned from server"); + } + } + } + } + ); +} + + +/** + * Logout the patron and return to the login page + */ +SelfCheckManager.prototype.logoutPatron = function(print) { + progressDialog.show(true); // prevent patron from clicking logout link twice + if(print && this.checkouts.length) { + this.printSessionReceipt( + function() { + location.href = location.href; + } + ); + } else { + location.href = location.href; + } +} + + +function checkLogin() { + selfCheckMgr.keepMeLoggedIn(); + if(selfCheckMgr.orgSettings[SET_PATRON_PASSWORD_REQUIRED]) { + switchTo('step2'); + try{dojo.byId('patron-login-password').focus();}catch(e){} + } else { + selfCheckMgr.loginPatron(dojo.byId('patron-login-username').value); + } +} + + +function cancelLogin() { + dojo.byId('oils-selfck-status-div').innerHTML = ''; + dojo.byId('oils-selfck-status-div2').innerHTML = ''; + dojo.byId('oils-selfck-status-div3').innerHTML = ''; + dojo.byId('patron-login-password').value = ''; + openils.Util.hide('back_to_login'); + switchTo('step1'); + try { + dojo.byId('patron-login-username').focus(); + dojo.byId('patron-login-username').select(); + } catch(e) {} +} + +/** + * Fire up the manager on page load + */ +openils.Util.addOnLoad( + function() { + new SelfCheckManager().init(); + openils.Util.registerEnterHandler(dojo.byId('patron-login-username'), function(){checkLogin();}); + openils.Util.registerEnterHandler(dojo.byId('patron-login-password'), function(){selfCheckMgr.loginPatron(dojo.byId('patron-login-username').value,dojo.byId('patron-login-password').value);}); + } +); diff --git a/Open-ILS/web/local_templates/base.tt2 b/Open-ILS/web/local_templates/base.tt2 new file mode 100644 index 0000000000..c95f117275 --- /dev/null +++ b/Open-ILS/web/local_templates/base.tt2 @@ -0,0 +1,27 @@ +[%- ctx.final_dtd = + '' -%] +[%- IF !ctx.dtd; ctx.dtd = ctx.final_dtd; END -%] +[% ctx.dtd %] + + + [% ctx.page_title %] + + + + + + + + + + + + [% INCLUDE login.tt2 %] + [% content %] + + diff --git a/Open-ILS/web/local_templates/base.tt2-aug17.old2 b/Open-ILS/web/local_templates/base.tt2-aug17.old2 new file mode 100644 index 0000000000..6bb7874aee --- /dev/null +++ b/Open-ILS/web/local_templates/base.tt2-aug17.old2 @@ -0,0 +1,26 @@ +[%- ctx.final_dtd = + '' -%] +[%- IF !ctx.dtd; ctx.dtd = ctx.final_dtd; END -%] +[% ctx.dtd %] + + + [% ctx.page_title %] + + + + + + + + + + + [% INCLUDE login.tt2 %] + [% content %] + + diff --git a/Open-ILS/web/local_templates/base.tt2.old b/Open-ILS/web/local_templates/base.tt2.old new file mode 100644 index 0000000000..9e7c8c36cd --- /dev/null +++ b/Open-ILS/web/local_templates/base.tt2.old @@ -0,0 +1,64 @@ +[%- ctx.final_dtd = + '' -%] +[%- ctx.home_path ='/local_templates/default/circ/selfcheck' -%] +[%- IF !ctx.dtd; ctx.dtd = ctx.final_dtd; END -%] +[% ctx.dtd %] + + + + [% ctx.page_title %] + + + + + + + + + + + + + + + + + +[% INCLUDE login.tt2 %] +[% content %] + + \ No newline at end of file diff --git a/Open-ILS/web/local_templates/default/actor/user/register_table.tt2.disabled b/Open-ILS/web/local_templates/default/actor/user/register_table.tt2.disabled new file mode 100644 index 0000000000..5083accce6 --- /dev/null +++ b/Open-ILS/web/local_templates/default/actor/user/register_table.tt2.disabled @@ -0,0 +1,116 @@ + + + + Parent/Guardian + + + + + + + + Address + + Mailing + Billing + + + + + + + This is a pending address: + +
+
+
+ + + + + + This address is owned by another user: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Verify Password + + + + + + + + + + + + + + + + + + User Settings + + + +
+ + + + + + + + + + + + + + + Statistical Categories + + + + + + + diff --git a/Open-ILS/web/local_templates/default/actor/user/register_table.tt2.orig b/Open-ILS/web/local_templates/default/actor/user/register_table.tt2.orig new file mode 100644 index 0000000000..e90e925121 --- /dev/null +++ b/Open-ILS/web/local_templates/default/actor/user/register_table.tt2.orig @@ -0,0 +1,98 @@ + + + + Parent/Guardian + + + + + + + + Address + + Mailing + Billing + + + + + + + This is a pending address: + +
+
+
+ + + + + + This address is owned by another user: + + + + + + + + + + + + + + + + + + + + + + Verify Password + + + + + + + + + + + + + + + + + + User Settings + + + +
+ + + + + + + + + + + + + + + Statistical Categories + + + + + + + diff --git a/Open-ILS/web/local_templates/default/base.tt2 b/Open-ILS/web/local_templates/default/base.tt2 new file mode 100644 index 0000000000..0570b12dda --- /dev/null +++ b/Open-ILS/web/local_templates/default/base.tt2 @@ -0,0 +1,39 @@ +[% WRAPPER 'base.tt2' %] + + + +
+
+ + + +
+ [% INCLUDE default/header.tt2 %] +
+
+
+ +
+ [% content %] +
+
+ +
+[% END %] diff --git a/Open-ILS/web/local_templates/default/base.tt2.old b/Open-ILS/web/local_templates/default/base.tt2.old new file mode 100644 index 0000000000..507fc1de79 --- /dev/null +++ b/Open-ILS/web/local_templates/default/base.tt2.old @@ -0,0 +1,41 @@ +[% WRAPPER 'base.tt2' %] + + +
+ + +
+ +
+
+
+ [% content %] +
+
+
+[% END %] diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/audio_config.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/audio_config.tt2 new file mode 100644 index 0000000000..9b084a1b50 --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/audio_config.tt2 @@ -0,0 +1,13 @@ +[%# + Override the audio config values by copying this template into your local templates + directory (matching the relative path) and change the values accordingly. +#%] + + diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/banner.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/banner.tt2 new file mode 100644 index 0000000000..cda4866c91 --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/banner.tt2 @@ -0,0 +1,10 @@ +
+
+ +
+
+
+ +
+
+ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/circ_page.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/circ_page.tt2 new file mode 100644 index 0000000000..868f5f9e35 --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/circ_page.tt2 @@ -0,0 +1,30 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
BarcodeTitleAuthorDue DateType
+ + +
+
diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/fines.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/fines.tt2 new file mode 100644 index 0000000000..fee782e197 --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/fines.tt2 @@ -0,0 +1,26 @@ + +Pay Fines +
+ + + + + + + + + + + + + + + + + + + + + +
TypeDetailsTotal BilledTotal PaidBalance Owed
+
diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/KCLS_logo_horiz.gif b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/KCLS_logo_horiz.gif new file mode 100644 index 0000000000..8e1d56ed5f Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/KCLS_logo_horiz.gif differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/arrow.gif b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/arrow.gif new file mode 100644 index 0000000000..bf17978429 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/arrow.gif differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/barcodedetailbook.jpg b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/barcodedetailbook.jpg new file mode 100644 index 0000000000..f0a237e924 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/barcodedetailbook.jpg differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/go-btn.png b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/go-btn.png new file mode 100644 index 0000000000..24091c9936 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/go-btn.png differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/gobutton.jpg b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/gobutton.jpg new file mode 100644 index 0000000000..33e7c380e5 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/gobutton.jpg differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/libcard_barcode.jpg b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/libcard_barcode.jpg new file mode 100644 index 0000000000..31419f65a5 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/libcard_barcode.jpg differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/login-btn.png b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/login-btn.png new file mode 100644 index 0000000000..ae9d9de5c7 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/login-btn.png differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logout.gif b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logout.gif new file mode 100644 index 0000000000..11d616015e Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logout.gif differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutbutton.jpg b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutbutton.jpg new file mode 100644 index 0000000000..61092eddb7 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutbutton.jpg differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutnoreceipt.gif b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutnoreceipt.gif new file mode 100644 index 0000000000..1c88f4adb5 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutnoreceipt.gif differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutwithoutreceiptbutton.jpg b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutwithoutreceiptbutton.jpg new file mode 100644 index 0000000000..20228bddb7 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/logoutwithoutreceiptbutton.jpg differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/printlist.jpg b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/printlist.jpg new file mode 100644 index 0000000000..a83c0fc575 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/printlist.jpg differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_font.gif b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_font.gif new file mode 100644 index 0000000000..9dc10a95f6 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_font.gif differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_mail.gif b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_mail.gif new file mode 100644 index 0000000000..83c357369e Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_mail.gif differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_print.gif b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_print.gif new file mode 100644 index 0000000000..d3d7ee388e Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/tool_print.gif differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/utils-corner-right.jpg b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/utils-corner-right.jpg new file mode 100644 index 0000000000..1559897142 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/utils-corner-right.jpg differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/utils-corner.jpg b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/utils-corner.jpg new file mode 100644 index 0000000000..4932a28672 Binary files /dev/null and b/Open-ILS/web/local_templates/default/circ/selfcheck/graphics/utils-corner.jpg differ diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/holds_page.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/holds_page.tt2 new file mode 100644 index 0000000000..333624948d --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/holds_page.tt2 @@ -0,0 +1,20 @@ +
+ + + + + + + + + + + + + + + + + +
TitleAuthorStatus
+
diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/main.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/main.tt2 new file mode 100644 index 0000000000..9c89e55324 --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/main.tt2 @@ -0,0 +1,238 @@ +[%- ctx.home_path ='/local_templates/default/circ/selfcheck' -%] +[% ctx.page_title = 'Self Checkout' %] +[% WRAPPER default/base.tt2 %] + + + +
+ + + + +
+ + +
+ +
+
+
+ + + + + +[% INCLUDE 'default/circ/selfcheck/audio_config.tt2' %] + +
Staff login required
+ + + + + + + + + +
+
+
+
+ +[% END %] \ No newline at end of file diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/patron_login.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/patron_login.tt2 new file mode 100644 index 0000000000..da65d791de --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/patron_login.tt2 @@ -0,0 +1,7 @@ +
Please login using your library barcode
+ + diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/payment.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/payment.tt2 new file mode 100644 index 0000000000..f4fe97eb6d --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/payment.tt2 @@ -0,0 +1,83 @@ +
+ Total amount to pay: $ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Credit Card #
CVV #
Exipration Month + +
Expiration Year
Edit Billing Details
First Name
Last Name
Street Address
City
State or Province
ZIP or Postal Code
+ +
diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/style.css b/Open-ILS/web/local_templates/default/circ/selfcheck/style.css new file mode 100644 index 0000000000..4f342db8fb --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/style.css @@ -0,0 +1,179 @@ +@charset "utf-8"; +/* CSS Document */ + +html, body { + margin:0; + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; + background:#333; + width:100%; +} + +img { + border: none; +} + +a { + color: #003399; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +h1 { + margin:0; + margin-bottom: 5px; + font-size: 20px; + font-weight:normal; +} + +h2 { + margin:0; + margin-bottom: 5px; + font-size: 14px; + font-weight:bold; +} + +#header { + color: #bda964; + font-weight:bold; + padding: 12px 0px 9px 17px; + width: 694px; + margin: auto; +} + +#content-wrapper { + background: white; + min-height: 260px; + border-bottom: 1px solid black; +} + +#main-content { + width: 694px; + margin:auto; + padding-left:17px; +} + +.checkout { + font-size:16px; +} + +.checkout h1 { + font-size:36px; +} + +.checkout h2 { + font-size:24px; +} + +.checkout .sidebar h3 { + font-size: 16px; + margin:0; + padding-left:3px; +} + +.checkout .sidebar a { + font-size:12px; +} + +.checkout .sidebar a span { + font-weight:bold; +} + +.checkout .sidebar p { + margin:4px 0px; + padding:3px; +} + +.checkout .sidebar div, .checkout .sidebar p { + font-size: 16px; + line-height: 1em; +} + +.checkout input[type=text], .checkout input[type=password] { + border: 1px solid black; + width:300px; + height:20px; + padding:2px; + padding-top:1px; + margin:0px; + font-size:16px; +} + +.checkout .sidebar { + background: #b0b0b0; + border-left:2px ridge #eee; + border-right:2px ridge #eee; + padding:10px 7px; +} + +.checkout .sidebar .top { + float:right; + padding-right:5px; +} + +.checkout .sidebar .greet { + clear:both; + padding:15px 3px; +} + +.checkout .sidebar .selected { + background:#999 +} + +.checkout .header1 { + height:108px; + border-bottom:1px solid #a83135; + padding-top:20px; +} + +.checkout .userid { + width:200px; + font-size:16px; + font-weight:bold; + padding:5px 6px 6px 6px !important; + border:2px solid black !important; + background: none !important; + margin:0 !important; +} + +.checkout .item_table { + border-collapse: collapse; +} + +.checkout .item_table td { + font-size:16px; + border:2px solid black; + text-align: left; +} + +.checkout .item_table table td.label { + font-weight:bold; + text-transform: uppercase; + text-align: right; + white-space:nowrap; + padding-right:5px; + width:1px; +} + +.checkout .item_table table td { + border:none; +} + +.checkout #back_button:hover { + text-decoration: none; +} + +.checkout .status_box { + color:red; + font-weight:bold; + height:20px; +} + +.checkout .oils-selfck-status-div { + height:inherit !important; + vertical-align:inherit !important; +} + diff --git a/Open-ILS/web/local_templates/default/circ/selfcheck/summary.tt2 b/Open-ILS/web/local_templates/default/circ/selfcheck/summary.tt2 new file mode 100644 index 0000000000..b037ad7d6b --- /dev/null +++ b/Open-ILS/web/local_templates/default/circ/selfcheck/summary.tt2 @@ -0,0 +1,27 @@ +
+ +
+ Items Checked Out +
+
+
View Items Out
+
+
+ Holds +
+
+
View Holds
+
+
+ Fines +
+
+ View Details +
+
+
+