Merged revisions 10174,10177-10179,10188,10190-10191,10193-10195,10199,10201-10202...
authorerickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 31 Jul 2008 15:45:25 +0000 (15:45 +0000)
committererickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 31 Jul 2008 15:45:25 +0000 (15:45 +0000)
svn://svn.open-ils.org/ILS/trunk

........
  r10174 | dbs | 2008-07-29 14:05:23 -0400 (Tue, 29 Jul 2008) | 2 lines

  Add default conify configuration to eg_vhost.conf
........
  r10177 | miker | 2008-07-29 14:40:11 -0400 (Tue, 29 Jul 2008) | 1 line

  removing unnecessary SetEnv[If] stuff
........
  r10178 | miker | 2008-07-29 15:10:57 -0400 (Tue, 29 Jul 2008) | 1 line

  thinko ... use the responder, which has the session, not the method pointer
........
  r10179 | miker | 2008-07-29 16:56:38 -0400 (Tue, 29 Jul 2008) | 1 line

  preferred language and date filter fixes
........
  r10188 | erickson | 2008-07-30 13:07:19 -0400 (Wed, 30 Jul 2008) | 6 lines

  Basic web-based selfcheck interface.  This interface implements a subset of

  http://open-ils.org/dokuwiki/doku.php?id=scratchpad:simple_self_check
........
  r10190 | erickson | 2008-07-30 13:09:39 -0400 (Wed, 30 Jul 2008) | 1 line

  oops, forgot the aliasmatch locale extraction for selfcheck
........
  r10191 | miker | 2008-07-30 13:37:44 -0400 (Wed, 30 Jul 2008) | 1 line

  add a reasonable prefix to autogenerated TCNs
........
  r10193 | erickson | 2008-07-30 14:01:28 -0400 (Wed, 30 Jul 2008) | 1 line

  falling back to existing is_true method
........
  r10194 | miker | 2008-07-30 14:17:19 -0400 (Wed, 30 Jul 2008) | 1 line

  adjustment to previous fix (create or replace ... so it it cut-n-paste friendly)
........
  r10195 | miker | 2008-07-30 14:18:53 -0400 (Wed, 30 Jul 2008) | 1 line

  ... and a typo fix to the fix
........
  r10199 | miker | 2008-07-30 22:51:44 -0400 (Wed, 30 Jul 2008) | 1 line

  dependency ordering of config functions
........
  r10201 | miker | 2008-07-30 23:56:24 -0400 (Wed, 30 Jul 2008) | 1 line

  dojo-based locale switcher
........
  r10202 | miker | 2008-07-31 00:08:39 -0400 (Thu, 31 Jul 2008) | 1 line

  replace does not, um, replace in place
........
  r10205 | miker | 2008-07-31 00:57:07 -0400 (Thu, 31 Jul 2008) | 1 line

  moving the lang switcher to a more reasonable location
........
  r10208 | phasefx | 2008-07-31 01:05:11 -0400 (Thu, 31 Jul 2008) | 1 line

  In Holdings Maintenance, we used to disable some render child behavior for the top of the org hierarchy, to prevent in the case of PINES, 200-odd libraries from being retrieved and rendered.  Now we check the can_have_vols for that org as well, to allow the interface to work with a single-org hierarchy
........
  r10211 | phasefx | 2008-07-31 01:13:12 -0400 (Thu, 31 Jul 2008) | 1 line

  we want to explicitly set net access level for new users or the db will provide a default
........
  r10212 | miker | 2008-07-31 01:21:54 -0400 (Thu, 31 Jul 2008) | 1 line

  make locale names and descriptions translatable
........
  r10213 | miker | 2008-07-31 01:22:51 -0400 (Thu, 31 Jul 2008) | 1 line

  more locale switch work
........
  r10214 | miker | 2008-07-31 01:40:58 -0400 (Thu, 31 Jul 2008) | 1 line

  make log message conditional
........
  r10215 | miker | 2008-07-31 01:46:01 -0400 (Thu, 31 Jul 2008) | 1 line

  use the correct field as the pkey
........
  r10216 | dbs | 2008-07-31 09:10:18 -0400 (Thu, 31 Jul 2008) | 2 lines

  Hush schema build messages that obscure potential real problems
........

git-svn-id: svn://svn.open-ils.org/ILS/branches/acq-experiment@10218 dcc99617-32d9-48b4-a31d-7c20da2025e4

20 files changed:
Evergreen/xul/staff_client/server/patron/ue.js
Open-ILS/examples/apache/eg.conf
Open-ILS/examples/apache/eg_vhost.conf
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm
Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm
Open-ILS/src/perlmods/OpenILS/Utils/CStoreEditor.pm
Open-ILS/src/sql/Pg/010.schema.biblio.sql
Open-ILS/src/sql/Pg/300.schema.staged_search.sql
Open-ILS/src/sql/Pg/build-db.sh
Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js
Open-ILS/web/opac/extras/selfcheck/selfcheck.css [new file with mode: 0644]
Open-ILS/web/opac/extras/selfcheck/selfcheck.js [new file with mode: 0644]
Open-ILS/web/opac/extras/selfcheck/selfcheck.xml [new file with mode: 0644]
Open-ILS/web/opac/extras/selfcheck/selfcheck_print.css [new file with mode: 0644]
Open-ILS/web/opac/locale/en-US/opac.dtd
Open-ILS/web/opac/skin/default/css/layout.css
Open-ILS/web/opac/skin/default/xml/common/fonts.xml
Open-ILS/web/opac/skin/default/xml/common/js_common.xml
Open-ILS/xul/staff_client/server/cat/copy_browser.js

index cb5a3d4..8ab42d2 100644 (file)
@@ -229,6 +229,7 @@ function uEditNewPatron() {
        card.isnew(1);
        patron.card(card);
        patron.cards([card]);
+    patron.net_access_level(defaultNetLevel);
        patron.stat_cat_entries([]);
        patron.survey_responses([]);
        patron.addresses([]);
index 3bee68a..2b654a5 100644 (file)
@@ -46,6 +46,7 @@ PerlChildInitHandler OpenILS::WWW::AddedContent::child_init;
 # ----------------------------------------------------------------------------------
 AliasMatch ^/opac/.*/skin/(.*)/(.*)/(.*) /openils/var/web/opac/skin/$1/$2/$3
 AliasMatch ^/opac/.*/extras/slimpac/(.*) /openils/var/web/opac/extras/slimpac/$1
+AliasMatch ^/opac/.*/extras/selfcheck/(.*) /openils/var/web/opac/extras/selfcheck/$1
 
 
 
index c1e523d..38d0ce5 100644 (file)
@@ -240,6 +240,21 @@ RewriteRule ^/opac/extras/ac/jacket/(small|medium|large)/$ \
 </Location>
 
 # ----------------------------------------------------------------------------------
+# Selfcheck interface
+# ----------------------------------------------------------------------------------
+<LocationMatch .*/selfcheck.xml>
+    SetHandler perl-script
+    PerlSetVar OILSProxyTitle "Selfcheck Login"
+    PerlSetVar OILSProxyDescription "Please log in to activate the selfcheck interface"
+    PerlSetVar OILSProxyPermissions "STAFF_LOGIN"
+    PerlHandler OpenILS::WWW::Proxy
+    Options +ExecCGI
+    PerlSendHeader On
+    allow from all
+</LocationMatch>
+
+
+# ----------------------------------------------------------------------------------
 # Reports GUI
 # ----------------------------------------------------------------------------------
 <LocationMatch /reports/>
@@ -258,10 +273,31 @@ RewriteRule ^/opac/extras/ac/jacket/(small|medium|large)/$ \
     allow from all
 </Location>
 
+# ----------------------------------------------------------------------------------
+# Conify - next-generation Evergreen administration interface
+# ----------------------------------------------------------------------------------
+RewriteEngine on
+RewriteRule ^/conify/.*/global/(.*)$ /conify/global/$1
+<Location /conify>
+    XMLEntStripPI "yes"
+    XMLEntEscapeScript "no"
+    XMLEntStripComments "yes"
+    XMLEntContentType "text/html; charset=utf-8"
+    AddOutputFilter INCLUDES .html
+    SetHandler perl-script
+    PerlSetVar OILSProxyTitle "Dojo Admin Login"
+    PerlSetVar OILSProxyDescription "Please log in to administer Evergreen"
+    PerlSetVar OILSProxyPermissions "STAFF_LOGIN"
+    PerlHandler OpenILS::WWW::Proxy
+    Options +ExecCGI
+    PerlSendHeader On
+    allow from all
+</Location>
+
 # OpenURL 0.1 searching based on OpenSearch
 RewriteEngine on
 RewriteMap openurl prg:/openils/bin/openurl_map.pl
 RewriteCond %{QUERY_STRING} (^.*$)
 RewriteRule ^/openurl$ ${openurl:%1} [NE,PT]
 
-
index d971535..3c50aa5 100644 (file)
@@ -3786,14 +3786,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                <links/>
        </class>
        <class id="i18n_l" controller="open-ils.cstore" oils_obj:fieldmapper="config::i18n_locale" oils_persist:tablename="config.i18n_locale" oils_persist:field_safe="true">
-               <fields oils_persist:primary="id">
+               <fields oils_persist:primary="code">
                        <field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
                        <field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
                        <field name="isdeleted" oils_obj:array_position="2" oils_persist:virtual="true" />
                        <field name="code" oils_obj:array_position="3" oils_persist:virtual="false" reporter:datatype="id" />
                        <field name="marc_code" oils_obj:array_position="4" oils_persist:virtual="false" reporter:datatype="text"/>
-                       <field name="name" oils_obj:array_position="5" oils_persist:virtual="false" reporter:datatype="text"/>
-                       <field name="description" oils_obj:array_position="6" oils_persist:virtual="false" reporter:datatype="text"/>
+                       <field name="name" oils_obj:array_position="5" oils_persist:virtual="false" reporter:datatype="text" oils_persist:i18n="true"/>
+                       <field name="description" oils_obj:array_position="6" oils_persist:virtual="false" reporter:datatype="text" oils_persist:i18n="true"/>
                </fields>
                <links/>
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
index d7b42a7..99f14e8 100644 (file)
@@ -11,14 +11,6 @@ my $U = "OpenILS::Application::AppUtils";
 my %scripts;
 my $script_libs;
 
-sub isTrue {
-    my $v = shift;
-    return 1 if ($v == 1);
-    return 1 if ($v =~ /^t/io);
-    return 1 if ($v =~ /^y/io);
-    return 0;
-}
-
 sub initialize {
 
     my $self = shift;
@@ -1072,7 +1064,7 @@ sub build_checkout_circ_object {
 
         # if is_percent is true then the max->amount is
         # use as a percentage of the copy price
-        if (isTrue($max->is_percent)) {
+        if ($U->is_true($max->is_percent)) {
 
             my $cn = $self->editor->retrieve_asset_call_number($copy->call_number);
 
index b89e1f5..9be3c6a 100644 (file)
@@ -2384,8 +2384,9 @@ sub staged_fts {
        my (@between,@statuses,@locations,@types,@forms,@lang,@aud,@lit_form,@vformats,@bib_level);
 
     if (!defined($args{preferred_language})) {
+               my $ses_locale = $client->session ? $client->session->session_locale : $default_preferred_language;
         $args{preferred_language} =
-            $locale_map{ $self->session->session_locale || $default_preferred_language } || 'eng';
+            $locale_map{ $ses_locale } || 'eng';
     }
 
     if (!defined($args{preferred_language_weight})) {
index 4e28ebc..e33e31e 100644 (file)
@@ -766,7 +766,7 @@ sub json_query {
         return undef;
     }
 
-    $self->log(I, "json_query : returned ".scalar(@$obj). " result(s)");
+    $self->log(I, "json_query : returned ".scalar(@$obj). " result(s)") if (ref($obj));
     return $obj;
 }
 
index 4a9794e..a7d66ab 100644 (file)
@@ -21,8 +21,8 @@ BEGIN;
 CREATE SCHEMA biblio;
 
 CREATE SEQUENCE biblio.autogen_tcn_value_seq;
-CREATE FUNCTION biblio.next_autogen_tcn_value () RETURNS TEXT AS $$
-       BEGIN RETURN nextval('biblio.autogen_tcn_value_seq'::TEXT); END;
+CREATE OR REPLACE FUNCTION biblio.next_autogen_tcn_value () RETURNS TEXT AS $$
+       BEGIN RETURN 'AUTOGENERATED-' || nextval('biblio.autogen_tcn_value_seq'::TEXT); END;
 $$ LANGUAGE PLPGSQL;
 
 CREATE TABLE biblio.record_entry (
index 7506d79..8014426 100644 (file)
@@ -344,7 +344,7 @@ BEGIN
         where_clause = where_clause || $$ AND $$ || quote_literal(param_during) || $$ BETWEEN mrd.date1 AND mrd.date2 $$;
     END IF;
 
-    IF param_between IS NOT NULL AND array_upper(param_between, 1) > 0 THEN
+    IF param_between IS NOT NULL AND array_upper(param_between, 1) > 1 THEN
         where_clause = where_clause || $$ AND mrd.date1 BETWEEN $$ || array_to_string(param_bib_level, $$' AND '$$) || ' ';
     END IF;
 
index 954a1b3..cac8c01 100755 (executable)
@@ -2,13 +2,14 @@
 
 # ---------------------------------------------------------------------------
 # Store command line args for later use
-# args: {db-host} {db-port} {db-name} {db-user} {db-password}
+# args: {db-host} {db-port} {db-name} {db-user} {db-password} {verbose}
 # ---------------------------------------------------------------------------
 PGHOST=$1
 PGPORT=$2
 PGDATABASE=$3
 PGUSER=$4
 PGPASSWORD=$5
+VERBOSE=$6
 export PGHOST PGPORT PGDATABASE PGUSER PGPASSWORD
 
 # ---------------------------------------------------------------------------
@@ -131,7 +132,12 @@ for sql_file in $ordered_file_list; do
   # export ON_ERROR_STOP=1
 
   export PGHOST PGPORT PGDATABASE PGUSER PGPASSWORD
-  psql -f $sql_file
+  # Hide most of the harmless messages that obscure real problems
+  if [ -z "$VERBOSE" ]; then
+    psql -f $sql_file 2>&1 | grep -v NOTICE | grep -v "^INSERT"
+  else
+    psql -f $sql_file
+  fi
   if [ $? != 0 ]; then
     cat <<EOM
 ********************************************************************************
index fb48a37..53393ad 100644 (file)
@@ -157,6 +157,7 @@ if(!dojo._hasResource["fieldmapper.Fieldmapper"]){
 
        }
 
+       fieldmapper.i18n_l.Identifier = 'code';
        fieldmapper.ppl.Identifier = 'code';
        fieldmapper.ccm.Identifier = 'code';
        fieldmapper.cvrfm.Identifier = 'code';
diff --git a/Open-ILS/web/opac/extras/selfcheck/selfcheck.css b/Open-ILS/web/opac/extras/selfcheck/selfcheck.css
new file mode 100644 (file)
index 0000000..b7aa882
--- /dev/null
@@ -0,0 +1,86 @@
+.hide_me {
+    visibility: hidden;
+    display: none;
+}
+table { border-collapse:collapse; }
+body { font-size: 12pt; }
+.container:after {content: ""; display: block; height: 0; clear: both; }
+
+.biglabel {
+    font-size: 13pt;
+    margin: 5px;
+}
+
+.selfck-link-span {
+    padding: 2px 4px 2px 4px;
+}
+
+#selfck-items-out-table {
+    width: 100%;
+}
+.form_div {
+    width:100%;
+}
+.form_div span {
+    padding: 5px;
+}
+
+#selfck-item-barcode-form {
+    margin-top:20px;
+}
+#selfck-items-out-table thead td {
+    font-weight: bold;
+}
+#selfck-items-out-table thead tr {
+    border-bottom: 2px solid #808080;
+}
+#selfck-items-out-table {
+    margin-top: 20px;
+}
+#selfck-items-out-tbody td { 
+    padding: 4px 0px 4px 0px;
+}
+#selfck-items-out-tbody tr { 
+    border-bottom: 1px solid #808080;
+}
+#selfck-pic-cell { width: 43px;}
+.jacket { height: 50px; width: 40px;  border: none;}
+
+#selfck-logout-div {
+    width: 100%;
+    margin: 0px 0px 0px 0px;
+    padding: 3px;
+    /*border-bottom:2px solid #e0f0e0;*/
+    text-align: right;
+}
+
+#selfck-patron-info-div {
+    text-align: left;
+    float:left;
+}
+#selfck-logout-link-div {
+    text-align: right;
+    float:right;
+}
+
+#selfck-message-div {
+    border: 1px solid #e0f0e0;
+    height: 1.5em;
+    overflow: auto;
+    margin-bottom: 20px;
+}
+#selfck-item-barcode-form-div {
+    text-align: center;
+}
+
+.print {
+    display: none;
+    visibility: hidden;
+}
+.noprint {
+    display: block;
+    visibility: visible;
+}
+
+
+
diff --git a/Open-ILS/web/opac/extras/selfcheck/selfcheck.js b/Open-ILS/web/opac/extras/selfcheck/selfcheck.js
new file mode 100644 (file)
index 0000000..3ac63e0
--- /dev/null
@@ -0,0 +1,307 @@
+/* -----------------------------------------------------------------
+* Copyright (C) 2008  Equinox Software, Inc.
+* Bill Erickson <erickson@esilibrary.com>
+* 
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+* 02110-1301, USA
+----------------------------------------------------------------- */
+
+var STAFF_SES_PARAM = 'ses';
+var patron = null
+var itemBarcode = null;
+var itemsOutTemplate = null;
+var isRenewal = false;
+var pendingXact = false;
+var patronTimeout = 120000;
+var timerId = null;
+var printWrapper;
+var printTemplate;
+var successfulItems = {};
+
+
+function selfckInit() {
+    var cgi = new CGI();
+    var staff = grabUser(cookieManager.read(STAFF_SES_PARAM) || cgi.param(STAFF_SES_PARAM));
+
+    /*
+    XXX we need org information (from the proxy?)
+    var t = fetchOrgSettingDefault(1, 'circ.selfcheck.patron_login_timeout');
+    patronTimeout = (t) ? parseInt(t) * 1000 : patronTimeout;
+    */
+
+    if(!staff) {
+        // should not happen when behind the proxy
+        return alert('Staff must login');
+    }
+
+    unHideMe($('selfck-patron-login-container'));
+    $('selfck-patron-login-input').focus();
+
+    $('selfck-patron-login-input').onkeypress = function(evt) {
+        if(userPressedEnter(evt)) 
+            selfckPatronLogin();
+    };
+
+    $('selfck-item-barcode-input').onkeypress = function(evt) {
+        if(userPressedEnter(evt)) 
+            selfckCheckout();
+    };
+
+    // for debugging, allow passing the user barcode via param
+    var urlbc = new CGI().param('patron');
+    if(urlbc)
+        selfckPatronLogin(urlbc);
+
+    selfckStartTimer();
+
+    printWrapper = $('selfck-print-items-list');
+    printTemplate = printWrapper.removeChild($n(printWrapper, 'selfck-print-items-template'));
+    itemsOutTemplate = $('selfck-items-out-tbody').removeChild($('selfck-items-out-row'));
+
+//    selfckMkDummyCirc(); // testing only
+}
+
+/*
+ * Start the logout timer
+ */
+function selfckStartTimer() {
+    timerId = setTimeout(
+        function() {
+            selfckLogoutPatron();
+        },
+        patronTimeout
+    );
+
+}
+
+/*
+ * Reset the logout timer
+ */
+function selfckResetTimer() {
+    clearTimeout(timerId);
+    selfckStartTimer();
+}
+
+/*
+ * Clears fields and "logs out" the patron by reloading the page
+ */
+function selfckLogoutPatron() {
+    $('selfck-item-barcode-input').value = ''; // prevent browser caching
+    $('selfck-patron-login-input').value = '';
+    if(patron) // page reload resets everything
+        location.href = location.href;
+}
+
+/*
+ * Fetches the user by barcode and displays the item barcode input
+ */
+
+function selfckPatronLogin(barcode) {
+    barcode = barcode || $('selfck-patron-login-input').value;
+    if(!barcode) return;
+
+    var bcReq = new Request(
+        'open-ils.actor:open-ils.actor.user.fleshed.retrieve_by_barcode',
+        G.user.session, barcode);
+
+       bcReq.request.alertEvent = false;
+
+    bcReq.callback(function(r) {
+        patron = r.getResultObject();
+        if(checkILSEvent(patron)) {
+            if(patron.textcode == 'ACTOR_USER_NOT_FOUND') {
+                unHideMe($('selfck-patron-not-found'));
+                $('selfck-patron-login-input').select();
+                return;
+            }
+            return alert(patron.textcode);
+        }
+        $('selfck-patron-login-input').value = ''; // reset the input
+        hideMe($('selfck-patron-login-container'));
+        unHideMe($('selfck-patron-checkout-container'));
+        $('selfck-patron-name-span').appendChild(text(patron.usrname()));
+        $('selfck-item-barcode-input').focus();
+    });
+
+    bcReq.send();
+}
+
+/**
+  * Sends the checkout request
+  */
+function selfckCheckout() {
+    if(pendingXact) return;
+    selfckResetTimer();
+    pendingXact = true;
+    isRenewal = false;
+
+    removeChildren($('selfck-event-time'));
+    removeChildren($('selfck-event-span'));
+
+    itemBarcode = $('selfck-item-barcode-input').value;
+    if(!itemBarcode) return;
+
+    if (itemBarcode in successfulItems) {
+        selfckShowMsgNode({textcode:'dupe-barcode'});
+        $('selfck-item-barcode-input').select();
+        pendingXact = false;
+        return;
+    }
+
+    var coReq = new Request(
+        'open-ils.circ:open-ils.circ.checkout.full',
+        G.user.session, {patron_id:patron.id(), copy_barcode:itemBarcode});
+
+       coReq.request.alertEvent = false;
+    coReq.callback(selfckHandleCoResult);
+    coReq.send();
+}
+
+/**
+  * Handles the resulting event.  If the item is already checked out,
+  * attempts renewal.  Any other events will display a message
+  */
+function selfckHandleCoResult(r) {
+    var evt = r.getResultObject();
+
+    if(evt.textcode == 'SUCCESS') {
+        selfckDislplayCheckout(evt);
+        selfckShowMsgNode(evt);
+        successfulItems[itemBarcode] = 1;
+
+    } else if(evt.textcode == 'OPEN_CIRCULATION_EXISTS') {
+        selfckRenew();
+
+    } else {
+        pendingXact = false;
+        selfckShowMsgNode(evt);
+        $('selfck-item-barcode-input').select();
+    }
+}
+
+/**
+  * Display event text in the messages block
+  */
+function selfckShowMsgNode(evt) {
+    var code = evt.textcode;
+    var msgspan = $('selfck-event-span');
+
+    // if we're not explicitly handling the event, just say "copy cannot circ"
+    if(!$('selfck-event-' + code)) 
+        code = 'COPY_CIRC_NOT_ALLOWED';
+
+    appendClear($('selfck-event-time'), text(new Date().toLocaleString()));
+    appendClear($('selfck-event-span'), text($('selfck-event-' + code).innerHTML));
+}
+
+/**
+  * Renders a row in the checkouts table for the current circulation
+  */
+function selfckDislplayCheckout(evt) {
+    unHideMe($('selfck-items-out-table'));
+
+    var template = itemsOutTemplate.cloneNode(true);
+    var copy = evt.payload.copy;
+    var record = evt.payload.record;
+    var circ = evt.payload.circ;
+
+    if(record.isbn()) {
+           var pic = $n(template, 'selfck.jacket');
+           pic.setAttribute('src', '../ac/jacket/small/'+cleanISBN(record.isbn()));
+    }
+    $n(template, 'selfck.barcode').appendChild(text(copy.barcode()));
+    $n(template, 'selfck.title').appendChild(text(record.title()));
+    $n(template, 'selfck.author').appendChild(text(record.author()));
+    $n(template, 'selfck.due_date').appendChild(text(circ.due_date().replace(/T.*/,'')));
+    $n(template, 'selfck.remaining').appendChild(text(circ.renewal_remaining()));
+    if(isRenewal) {
+        hideMe($n(template, 'selfck.cotype_co'));
+        unHideMe($n(template, 'selfck.cotype_rn'));
+    }
+
+    $('selfck-items-out-tbody').appendChild(template);
+    $('selfck-item-barcode-input').value = '';
+
+
+    // flesh out the printable version of the page as well
+    var ptemplate = printTemplate.cloneNode(true);
+    $n(ptemplate, 'title').appendChild(text(record.title()));
+    $n(ptemplate, 'barcode').appendChild(text(copy.barcode()));
+    $n(ptemplate, 'due_date').appendChild(text(circ.due_date().replace(/T.*/,'')));
+    printWrapper.appendChild(ptemplate);
+
+    pendingXact = false;
+}
+
+/**
+  * Checks to see if this item is checked out to the current patron.  If so, 
+  * this sends the renewal request.
+  */
+function selfckRenew() {
+
+    // first, make sure the item is checked out to this patron
+    var detailReq = new Request(
+        'open-ils.circ:open-ils.circ.copy_details.retrieve.barcode',
+        G.user.session, itemBarcode);
+
+    detailReq.callback(
+        function(r) {
+            var details = r.getResultObject();
+            if(details.circ.usr() == patron.id()) {
+                // OK, this is our item, renew it
+                isRenewal = true;
+                var rnReq = new Request(
+                    'open-ils.circ:open-ils.circ.renew',
+                    G.user.session, {copy_barcode:itemBarcode});
+                rnReq.request.alertEvent = false;
+                rnReq.callback(selfckHandleCoResult);
+                rnReq.send();
+            }
+        }
+    );
+
+    detailReq.send();
+}
+
+/**
+  * Sets the print date and prints the page
+  */
+function selfckPrint() {
+    appendClear($('selfck-print-date'), text(new Date().toLocaleString()));
+    window.print();
+}
+
+
+/**
+  * Test method for generating dummy data in the checkout tables
+  */
+function selfckMkDummyCirc() {
+    unHideMe($('selfck-items-out-table'));
+
+    var template = itemsOutTemplate.cloneNode(true);
+    $n(template, 'selfck.barcode').appendChild(text('123456789'));
+    $n(template, 'selfck.title').appendChild(text('Test Title'));
+    $n(template, 'selfck.author').appendChild(text('Test Author'));
+    $n(template, 'selfck.due_date').appendChild(text('2008-08-01'));
+    $n(template, 'selfck.remaining').appendChild(text('1'));
+    $('selfck-items-out-tbody').appendChild(template);
+
+    // flesh out the printable version of the page as well
+    var ptemplate = printTemplate.cloneNode(true);
+    $n(ptemplate, 'title').appendChild(text('Test Title'));
+    $n(ptemplate, 'barcode').appendChild(text('123456789'));
+    $n(ptemplate, 'due_date').appendChild(text('2008-08-01'));
+    printWrapper.appendChild(ptemplate);
+}
diff --git a/Open-ILS/web/opac/extras/selfcheck/selfcheck.xml b/Open-ILS/web/opac/extras/selfcheck/selfcheck.xml
new file mode 100644 (file)
index 0000000..b2a98dc
--- /dev/null
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ***********************************************************************
+* Copyright (C) 2008  Equinox Software, Inc.
+* Bill Erickson <erickson@esilibrary.com>
+* 
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+* 02110-1301, USA
+************************************************************************ -->
+
+<!DOCTYPE html PUBLIC 
+       "-//W3C//DTD XHTML 1.0 Transitional//EN" 
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
+       <!--#include virtual="/opac/locale/${locale}/opac.dtd" -->
+]>
+
+<!--#include virtual="../../skin/default/xml/setenv.xml"-->
+
+<html xmlns='http://www.w3.org/1999/xhtml'>
+
+    <head>
+        <script>var config = {css:{}}</script>
+               <!--#include virtual="../../skin/default/xml/common/js_common.xml"-->
+        <script language='javascript' type='text/javascript' 
+            src='<!--#echo var="OILS_OPAC_JS_HOST"-->/common/js/DP_DateExtensions.js'></script>
+        <script language='javascript' type='text/javascript' 
+            src='<!--#echo var="OILS_OPAC_JS_HOST"-->/extras/selfcheck/selfcheck.js'></script>
+        <link type='text/css' rel='stylesheet' title='Regular'
+            href="<!--#echo var='OILS_OPAC_CSS_HOST'-->/extras/selfcheck/selfcheck.css"/>
+        <link type='text/css' rel='stylesheet' media='print'
+            href="<!--#echo var='OILS_OPAC_CSS_HOST'-->/extras/selfcheck/selfcheck_print.css"/>
+        <link type='text/css' rel='alternate stylesheet' title='Printable'
+            href="<!--#echo var='OILS_OPAC_CSS_HOST'-->/extras/selfcheck/selfcheck_print.css"/>
+    </head>
+
+    <body onload='selfckInit();'>
+
+        <div class='noprint'>
+
+            <!--***********************************************************************
+                Form for patron "login"
+                *********************************************************************** -->
+            <div id='selfck-patron-login-container' class='hide_me form_div'>
+                <span>&selfck.patron_barcode_label;</span>
+                <span><input type='text' id='selfck-patron-login-input'> </input></span>
+                <span><button onclick='selfckPatronLogin();'>&selfck.submit;</button></span>
+                <span id='selfck-patron-not-found' class='hide_me'>&selfck.event.patron_not_found;</span>
+            </div>
+
+            <!--***********************************************************************
+                Checkout form
+                *********************************************************************** -->
+            <div id='selfck-patron-checkout-container' class='hide_me'>
+
+                <!--***********************************************************************
+                    Header
+                    *********************************************************************** -->
+                <div id='selfck-logout-div' class='container'>
+                    <div id='selfck-patron-info-div'> 
+                        <!-- not really i18n friendly, but better than nothing -->
+                        &selfck.welcome; <span id='selfck-patron-name-span'></span>!
+                    </div>
+                    <div id='selfck-logout-link-div'>
+                        <span class='selfck-link-span'>
+                            <a href='javascript:void(0);' id='selfck-print-co-button' 
+                                onclick='selfckPrint();'>&selfck.print_checkouts;</a>
+                        </span>
+                        <span class='selfck-link-span'>
+                            <a href='javascript:void(0);' id='selfck-logout-button' 
+                                onclick='selfckLogoutPatron();'>&selfck.logout;</a>
+                        </span>
+                        <span class='selfck-link-span'>
+                            <a href='javascript:void(0);' id='selfck-logout-print-button' 
+                                onclick='selfckPrint(); selfckLogoutPatron();'>&selfck.print_logout;</a>
+                        </span>
+                    </div>
+                </div>
+
+                <!--***********************************************************************
+                    Display messages here
+                    *********************************************************************** -->
+                <div id='selfck-message-div' class='form_div'>
+                    <span class='' id='selfck-event-time'></span>
+                    <span class='biglabel' id='selfck-event-span'> </span>
+                    <span class='hide_me'>
+                        <span id='selfck-event-SUCCESS'>&selfck.event.co_success;</span>
+                        <span id='selfck-event-UNKNOWN'>&selfck.event.unknown;</span>
+                        <span id='selfck-event-ACTOR_USER_NOT_FOUND'>&selfck.event.patron_not_found;</span>
+                        <span id='selfck-event-COPY_CIRC_NOT_ALLOWED'>&selfck.event.item_nocirc;</span>
+                        <span id='selfck-event-ITEM_NOT_CATALOGED'>&selfck.event.item_noncat;</span>
+                        <span id='selfck-event-dupe-barcode'>&selfck.event.dupe_barcode;</span>
+                    </span>
+                </div>
+
+                <!--***********************************************************************
+                    This is where patrons scan in the item barcodes
+                    *********************************************************************** -->
+                <div id='selfck-item-barcode-form-div' class='form_div'>
+                    <div>
+                        <img src='../../../images/small_logo.jpg'/>
+                        <div class='biglabel'>&selfck.item_barcode_label;</div>
+                        <div id='selfck-item-barcode-form'>
+                            <span><input type='text' id='selfck-item-barcode-input'> </input></span>
+                            <span><button onclick='selfckCheckout();'>&selfck.submit;</button></span>
+                        </div>
+                    </div>
+                </div>
+
+                <!--***********************************************************************
+                    This is where patrons scan in the item barcodes
+                    *********************************************************************** -->
+                <table id='selfck-items-out-table' class='hide_me'>
+                    <thead>
+                        <tr>
+                            <td id='selfck-pic-cell'></td>
+                            <td>&selfck.barcode;</td>
+                            <td>&selfck.title;</td>
+                            <td>&selfck.author;</td>
+                            <td>&selfck.due_date;</td>
+                            <td>&selfck.remaining;</td>
+                            <td>&selfck.cotype;</td>
+                        </tr>
+                    </thead>
+                    <tbody id='selfck-items-out-tbody'>
+                        <tr id='selfck-items-out-row'>
+                            <td><img class='jacket' name='selfck.jacket'></img></td>
+                            <td name='selfck.barcode'></td>
+                            <td name='selfck.title'></td>
+                            <td name='selfck.author'></td>
+                            <td name='selfck.due_date'></td>
+                            <td name='selfck.remaining'></td>
+                            <td>
+                                <span name='selfck.cotype_co'>&selfck.cotype_co;</span>
+                                <span name='selfck.cotype_rn' class='hide_me'>&selfck.cotype_rn;</span>
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+        </div>
+
+        <!--***********************************************************************
+            Generate the printable version of the checked out list here
+            *********************************************************************** -->
+        <div class='print' id='selfck-print-div'>
+            <div>
+                <div id='selfck-print-date'/>
+                You checked out the following items:
+                <ol id='selfck-print-items-list'>
+                    <li name='selfck-print-items-template'>
+                        <div name='title'/>
+                        Barcode: <span name='barcode'/>
+                        Due Date: <span name='due_date'/>
+                    </li>
+                </ol>
+            </div>
+        </div>
+    </body>
+</html>
+
diff --git a/Open-ILS/web/opac/extras/selfcheck/selfcheck_print.css b/Open-ILS/web/opac/extras/selfcheck/selfcheck_print.css
new file mode 100644 (file)
index 0000000..18cd1ee
--- /dev/null
@@ -0,0 +1,15 @@
+.noprint {
+    display: none;
+    visibility: hidden;
+}
+.print {
+    display: block;
+    visibility: visible;
+    width: 100%;
+    font-size: 10pt;
+    color: black;
+    font-family: Arial;
+    background-color: white;
+}
+
+
index 7fed843..c493fbb 100644 (file)
@@ -6,6 +6,7 @@
 <!ENTITY lang.author "PINES">
 <!ENTITY common.all "All">
 <!ENTITY common.currency "$">
+<!ENTITY common.language "Language: ">
 <!ENTITY common.name "Name">
 <!ENTITY common.none "None">
 <!ENTITY common.title "Title">
@@ -634,3 +635,36 @@ Ensure Caps-Lock is off and try again or contact your local library.">
 <!ENTITY opac.image_provided "Image provided by">
 <!ENTITY vendor.name "Amazon">
 <!ENTITY vendor.base_link "http://amazon.com/dp/">
+
+
+
+<!--   ================================================================= 
+       Selfcheck
+       ================================================================= -->
+<!ENTITY selfck.staff_login_label "Staff login">
+<!ENTITY selfck.staff_login "Library barcode or username">
+<!ENTITY selfck.staff_pw "Password">
+<!ENTITY selfck.submit "Submit">
+<!ENTITY selfck.patron_barcode_label "Please scan your library barcode">
+<!ENTITY selfck.item_barcode_label "Please scan an item to checkout or renew:">
+<!ENTITY selfck.barcode "Barcode">
+<!ENTITY selfck.title "Title">
+<!ENTITY selfck.author "Author">
+<!ENTITY selfck.due_date "Due Date">
+<!ENTITY selfck.remaining "Renewals Remaining">
+<!ENTITY selfck.cotype "Type">
+<!ENTITY selfck.cotype_co "Checkout">
+<!ENTITY selfck.cotype_rn "Renewal">
+<!ENTITY selfck.logout "Logout">
+<!ENTITY selfck.print_logout "Print &amp; Logout">
+<!ENTITY selfck.welcome "Welcome">
+
+<!-- event messages -->
+<!ENTITY selfck.event.co_success "Check out succeeded">
+<!ENTITY selfck.event.co_unknown "An unknown event has occurred">
+<!ENTITY selfck.event.dupe_barcode "This item has already been checked out during this session">
+<!ENTITY selfck.event.patron_not_found "The patron barcode was not found">
+<!ENTITY selfck.event.item_noncat "The requested item is not in the catalog">
+<!ENTITY selfck.event.item_nocirc "The requested item is not allowed to circulate">
+<!ENTITY selfck.print_checkouts "Print Receipt">
+
index 0eae7a7..e0f7971 100644 (file)
@@ -74,7 +74,7 @@ table { border-collapse: collapse; }
 
 /* ---------------------------------------------------------------------- */
 
-#searchbar { margin-top: 18px; width: 100%; }
+#searchbar { margin-top: 22px; width: 100%; }
 #searchbar table tr td {font-weight: bold; font-size: 8pt; }
 #searchbar select, input { border-collapse: collapse; font-size: 9pt; }
 .searchbar_item { margin: 3px; font-size: 9pt; } 
index 5c19b0a..73cab30 100644 (file)
@@ -1,10 +1,19 @@
 <div id='fonts_div'>
 
        <div id='text_size_div' style='position:absolute; top: 2px; right: 6px;'>
-               <span>&common.textsize.title;</span>
-               <span><a href="javascript:void(0);" onclick="setFontSize('regular');"> &common.textsize.regular; </a></span>
-               <span> &common.textsize.separator; </span>
-               <span><a href="javascript:void(0);" onclick="setFontSize('large');"> &common.textsize.large; </a></span>
+               <span style='vertical-align: top;'>&common.textsize.title;</span>
+               <span style='vertical-align: top;'><a href="javascript:void(0);" onclick="setFontSize('regular');"> &common.textsize.regular; </a></span>
+               <span style='vertical-align: top;'> &common.textsize.separator; </span>
+               <span style='vertical-align: top;'><a href="javascript:void(0);" onclick="setFontSize('large');"> &common.textsize.large; </a></span>
+               <span style='vertical-align: top;'>&nbsp;<span style="font-weight:bold;">|</span>&nbsp;</span>
+               <span style='vertical-align: top;'>&common.language;</span>
+               <span id='translation_switch' dojoType="dijit.form.FilteringSelect" store="openils.I18N.localeStore" searchAttr="label" required="false">
+                       <script type="dojo/label" event="onChange">
+                               if (this.getValue()) {
+                                       location.href = location.href.replace( /opac\/[^\/]+\/skin/, 'opac/' + this.getValue() + '/skin');
+                               }
+                       </script>
+               </span>
        </div>
        
 </div>
index b390e8d..79e179c 100644 (file)
 
     <!-- enable Dojo date picker -->
     <script language='javascript' type="text/javascript">
-        var djConfig = {parseOnLoad: true, isDebug: false},
-            locale,
-            lang,
-            bidi;
 
-        djConfig.locale = '<!--#echo var="locale"-->';
+        var djConfig = {parseOnLoad: true, isDebug: false}, lang, bidi;
+
+        var locale = location.href.replace( /.+opac\/([^\/]+)\/skin.+/, '$1' );
+        if (!locale) locale = '<!--#echo var="locale"-->';
+
+        djConfig.locale = locale;
+
     </script>
 
     <script type="text/javascript" src='/js/dojo/dojo/dojo.js'></script>
@@ -51,4 +53,6 @@
         dojo.require("dojo.date.locale");
         dojo.require("dojo.date.stamp");
         dojo.require("dojo.parser");
+        dojo.require("openils.I18N");
+        dojo.require("dijit.form.FilteringSelect");
     </script>
index e7e43ed..6e30761 100644 (file)
@@ -1220,8 +1220,7 @@ cat.copy_browser.prototype = {
        'on_select_org' : function(org_id,twisty) {
                var obj = this;
                var org = obj.data.hash.aou[ org_id ];
-               if (obj.data.hash.aout[ org.ou_type() ].depth() == 0) return; 
-               /* otherwise, we'd show every system in the consortia */
+        if (obj.data.hash.aout[ org.ou_type() ].depth() == 0 && ! get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) return;
                var funcs = [];
                funcs.push( function() { 
                        document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
@@ -1340,7 +1339,7 @@ cat.copy_browser.prototype = {
                        }
 
                        if (document.getElementById('show_acns').checked) {
-                               if ( obj.data.hash.aout[ org.ou_type() ].depth() != 0 ) {
+                if (! ( obj.data.hash.aout[ org.ou_type() ].depth() == 0 && ! get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) )) {
                                        node.setAttribute('open','true');
                                        setTimeout( function() { obj.on_select_org( org.id() ); }, 0 );
                                }