Merged revisions 10219-10220,10223,10225,10228-10229,10231-10233,10236-10237,10240...
authorerickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 4 Aug 2008 01:25:53 +0000 (01:25 +0000)
committererickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 4 Aug 2008 01:25:53 +0000 (01:25 +0000)
svn://svn.open-ils.org/ILS/trunk

........
  r10219 | erickson | 2008-07-31 11:53:44 -0400 (Thu, 31 Jul 2008) | 12 lines

  Upped the default patron timeout to 10 minutes

  When an item barcode is scanned but the Enter key is not sent,
  the system waits a configured amount of time (default 800 milliseconds)
  then selects the text so the next scan will replace the existing text.

  Automatically print at logout time

  Replace Logout and Print links with "Done" links since printing is assumed
........
  r10220 | miker | 2008-07-31 12:16:11 -0400 (Thu, 31 Jul 2008) | 1 line

  make grace period a command line parameter
........
  r10223 | erickson | 2008-07-31 12:28:30 -0400 (Thu, 31 Jul 2008) | 1 line

  added explicit DESTROY methods to each package so AUTOLOAD won't attempt to use it
........
  r10225 | erickson | 2008-07-31 12:44:46 -0400 (Thu, 31 Jul 2008) | 1 line

  if a patron barcode regex is configured and a patron barcode is scanned into the item barcode input, the current user is logged out and the new user is logged in
........
  r10228 | erickson | 2008-07-31 14:55:38 -0400 (Thu, 31 Jul 2008) | 1 line

  if you set signed.applets.codebase_principal_support to true in about:config in Firefox, you now have the option to bypass the printer dialog if you accept the security dialogs
........
  r10229 | dbs | 2008-07-31 22:47:39 -0400 (Thu, 31 Jul 2008) | 2 lines

  No leading period for selector, please.
........
  r10231 | dbs | 2008-08-01 12:21:15 -0400 (Fri, 01 Aug 2008) | 2 lines

  D'oh! That 404 error really does mean that osrf-http-translator could not be found.
........
  r10232 | erickson | 2008-08-01 12:45:45 -0400 (Fri, 01 Aug 2008) | 1 line

  removed ":" from log line so output can be pasted directly into srfsh
........
  r10233 | erickson | 2008-08-01 13:04:08 -0400 (Fri, 01 Aug 2008) | 7 lines

  fixed faulty rule set query
  made some var names more explicit
  fix getopt setting
........
  r10236 | miker | 2008-08-01 14:00:30 -0400 (Fri, 01 Aug 2008) | 1 line

  add support for selecting from a function, given the function name and all params in an array (and the function takes only TEXT params)
........
  r10237 | miker | 2008-08-01 14:57:44 -0400 (Fri, 01 Aug 2008) | 1 line

  ingest of dates thinko
........
  r10240 | erickson | 2008-08-03 19:57:06 -0400 (Sun, 03 Aug 2008) | 1 line

  "parent" is a special variable.  some browsers (opera) will complain
........
  r10241 | erickson | 2008-08-03 19:58:09 -0400 (Sun, 03 Aug 2008) | 1 line

  "parent" is a special variable.  some browsers (opera) will complain
........

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

14 files changed:
Open-ILS/examples/apache/eg_vhost.conf
Open-ILS/src/c-apps/oils_cstore.c
Open-ILS/src/perlmods/OpenILS/Application/Ingest.pm
Open-ILS/src/perlmods/OpenILS/Utils/CStoreEditor.pm
Open-ILS/src/perlmods/OpenILS/Utils/ZClient.pm
Open-ILS/src/support-scripts/fine_generator.pl
Open-ILS/src/support-scripts/test-scripts/indb_circ.pl
Open-ILS/web/js/dojo/fieldmapper/OrgUtils.js
Open-ILS/web/opac/common/js/org_utils.js
Open-ILS/web/opac/extras/selfcheck/selfcheck.css
Open-ILS/web/opac/extras/selfcheck/selfcheck.js
Open-ILS/web/opac/extras/selfcheck/selfcheck.xml
Open-ILS/web/opac/locale/en-US/opac.dtd
Open-ILS/web/opac/skin/default/js/myopac.js

index 38d0ce5..badf40b 100644 (file)
@@ -207,7 +207,7 @@ RewriteRule ^/opac/extras/ac/jacket/(small|medium|large)/$ \
 # OpenSRF-over-HTTP translator
 # (http://open-ils.org/dokuwiki/doku.php?id=opensrf_over_http)
 # ----------------------------------------------------------------------------------
-<Location /osrf_http_translator>
+<Location /osrf-http-translator>
     SetHandler osrf_http_translator_module
     allow from all
 </Location>
index 63bdc77..c580fa3 100644 (file)
@@ -1725,6 +1725,7 @@ static char* SELECT (
        jsonObject* found = NULL;
 
        char* string = NULL;
+       int from_function = 0;
        int first = 1;
        int gfirst = 1;
        //int hfirst = 1;
@@ -1752,13 +1753,17 @@ static char* SELECT (
                jsonIteratorFree( tmp_itr );
                snode = NULL;
 
+       } else if (join_hash->type == JSON_ARRAY) {
+        from_function = 1;
+        selhash = NULL;
+
        } else if (join_hash->type == JSON_STRING) {
                core_class = jsonObjectToSimpleString( join_hash );
                join_hash = NULL;
        }
 
-       // punt if we don't know about the core class
-       if (!(core_meta = osrfHashGet( oilsIDL(), core_class ))) {
+       // punt if we don't know about the core class (and it's not a function)
+       if (!from_function && !(core_meta = osrfHashGet( oilsIDL(), core_class ))) {
                free(core_class);
                return NULL;
        }
@@ -1786,7 +1791,8 @@ static char* SELECT (
        growing_buffer* group_buf = buffer_init(128);
        growing_buffer* having_buf = buffer_init(128);
 
-       core_fields = osrfHashGet(core_meta, "fields");
+       if (!from_function) 
+        core_fields = osrfHashGet(core_meta, "fields");
 
        // ... and if we /are/ building the default list, do that
        if ( (_tmp = jsonObjectGetKey(selhash,core_class)) && !_tmp->size ) {
@@ -1794,355 +1800,366 @@ static char* SELECT (
                int i = 0;
                char* field;
 
-               osrfStringArray* keys = osrfHashKeys( core_fields );
-               while ( (field = osrfStringArrayGetString(keys, i++)) ) {
-                       if ( strncasecmp( "true", osrfHashGet( osrfHashGet( core_fields, field ), "virtual" ), 4 ) )
-                               jsonObjectPush( _tmp, jsonNewObject( field ) );
-               }
-               osrfStringArrayFree(keys);
+        if (!from_function) {
+               osrfStringArray* keys = osrfHashKeys( core_fields );
+               while ( (field = osrfStringArrayGetString(keys, i++)) ) {
+                       if ( strncasecmp( "true", osrfHashGet( osrfHashGet( core_fields, field ), "virtual" ), 4 ) )
+                               jsonObjectPush( _tmp, jsonNewObject( field ) );
+               }
+               osrfStringArrayFree(keys);
+        }
        }
 
        // Now we build the actual select list
-       int sel_pos = 1;
-       jsonObject* is_agg = jsonObjectFindPath(selhash, "//aggregate");
-       first = 1;
-       gfirst = 1;
-       jsonIterator* selclass_itr = jsonNewIterator( selhash );
-       while ( (selclass = jsonIteratorNext( selclass_itr )) ) {
-
-               // round trip through the idl, just to be safe
-               idlClass = osrfHashGet( oilsIDL(), selclass_itr->key );
-               if (!idlClass) continue;
-               char* cname = osrfHashGet(idlClass, "classname");
-
-               // make sure the target relation is in the join tree
-               if (strcmp(core_class,cname)) {
-                       if (!join_hash) continue;
-
-                       if (join_hash->type == JSON_STRING) {
-                               string = jsonObjectToSimpleString(join_hash);
-                               found = strcmp(string,cname) ? NULL : jsonParseString("{\"1\":\"1\"}");
-                               free(string);
-                       } else {
-                               found = jsonObjectFindPath(join_hash, "//%s", cname);
-                       }
-
-                       if (!found->size) {
-                               jsonObjectFree(found);
-                               continue;
-                       }
-
-                       jsonObjectFree(found);
-               }
-
-               // stitch together the column list ...
-               jsonIterator* select_itr = jsonNewIterator( selclass );
-               while ( (selfield = jsonIteratorNext( select_itr )) ) {
-
-                       char* __column = NULL;
-                       char* __alias = NULL;
-
-                       // ... if it's a sstring, just toss it on the pile
-                       if (selfield->type == JSON_STRING) {
-
-                               // again, just to be safe
-                               char* _requested_col = jsonObjectToSimpleString(selfield);
-                               osrfHash* field = osrfHashGet( osrfHashGet( idlClass, "fields" ), _requested_col );
-                               free(_requested_col);
-
-                               if (!field) continue;
-                               __column = strdup(osrfHashGet(field, "name"));
-
-                               if (first) {
-                                       first = 0;
-                               } else {
-                                       buffer_add(select_buf, ",");
-                               }
-
-                if (locale) {
-                       char* i18n = osrfHashGet(field, "i18n");
-                               if (flags & DISABLE_I18N)
-                        i18n = NULL;
-
-                       if ( i18n && !strncasecmp("true", i18n, 4)) {
-                           char* pkey = osrfHashGet(idlClass, "primarykey");
-                           char* tname = osrfHashGet(idlClass, "tablename");
-
-                        buffer_fadd(select_buf, " oils_i18n_xlate('%s', '%s', '%s', '%s', \"%s\".%s::TEXT, '%s') AS \"%s\"", tname, cname, __column, pkey, cname, pkey, locale, __column);
-                    } else {
-                                       buffer_fadd(select_buf, " \"%s\".%s AS \"%s\"", cname, __column, __column);
-                    }
-                } else {
-                                   buffer_fadd(select_buf, " \"%s\".%s AS \"%s\"", cname, __column, __column);
-                }
-
-                       // ... but it could be an object, in which case we check for a Field Transform
-                       } else {
-
-                               __column = jsonObjectToSimpleString( jsonObjectGetKeyConst( selfield, "column" ) );
-
-                               // again, just to be safe
-                               osrfHash* field = osrfHashGet( osrfHashGet( idlClass, "fields" ), __column );
-                               if (!field) continue;
-                               const char* fname = osrfHashGet(field, "name");
-
-                               if (first) {
-                                       first = 0;
-                               } else {
-                                       buffer_add(select_buf, ",");
-                               }
+       if (!from_function) {
+           int sel_pos = 1;
+           jsonObject* is_agg = jsonObjectFindPath(selhash, "//aggregate");
+           first = 1;
+           gfirst = 1;
+           jsonIterator* selclass_itr = jsonNewIterator( selhash );
+           while ( (selclass = jsonIteratorNext( selclass_itr )) ) {
+
+                   // round trip through the idl, just to be safe
+                   idlClass = osrfHashGet( oilsIDL(), selclass_itr->key );
+                   if (!idlClass) continue;
+                   char* cname = osrfHashGet(idlClass, "classname");
+
+                   // make sure the target relation is in the join tree
+                   if (strcmp(core_class,cname)) {
+                           if (!join_hash) continue;
+
+                           if (join_hash->type == JSON_STRING) {
+                                   string = jsonObjectToSimpleString(join_hash);
+                                   found = strcmp(string,cname) ? NULL : jsonParseString("{\"1\":\"1\"}");
+                                   free(string);
+                           } else {
+                                   found = jsonObjectFindPath(join_hash, "//%s", cname);
+                           }
+
+                           if (!found->size) {
+                                   jsonObjectFree(found);
+                                   continue;
+                           }
+
+                           jsonObjectFree(found);
+                   }
+
+                   // stitch together the column list ...
+                   jsonIterator* select_itr = jsonNewIterator( selclass );
+                   while ( (selfield = jsonIteratorNext( select_itr )) ) {
+
+                           char* __column = NULL;
+                           char* __alias = NULL;
+
+                           // ... if it's a sstring, just toss it on the pile
+                           if (selfield->type == JSON_STRING) {
+
+                                   // again, just to be safe
+                                   char* _requested_col = jsonObjectToSimpleString(selfield);
+                                   osrfHash* field = osrfHashGet( osrfHashGet( idlClass, "fields" ), _requested_col );
+                                   free(_requested_col);
+
+                                   if (!field) continue;
+                                   __column = strdup(osrfHashGet(field, "name"));
+
+                                   if (first) {
+                                           first = 0;
+                                   } else {
+                                           buffer_add(select_buf, ",");
+                                   }
 
-                               if ((tmp_const = jsonObjectGetKeyConst( selfield, "alias" ))) {
-                                       __alias = jsonObjectToSimpleString( tmp_const );
-                               } else {
-                                       __alias = strdup(__column);
-                               }
-
-                               if (jsonObjectGetKeyConst( selfield, "transform" )) {
-                                       free(__column);
-                                       __column = searchFieldTransform(cname, field, selfield);
-                                       buffer_fadd(select_buf, " %s AS \"%s\"", __column, __alias);
-                               } else {
                     if (locale) {
-                               char* i18n = osrfHashGet(field, "i18n");
+                           char* i18n = osrfHashGet(field, "i18n");
                                    if (flags & DISABLE_I18N)
                             i18n = NULL;
 
-                               if ( i18n && !strncasecmp("true", i18n, 4)) {
+                           if ( i18n && !strncasecmp("true", i18n, 4)) {
                                char* pkey = osrfHashGet(idlClass, "primarykey");
                                char* tname = osrfHashGet(idlClass, "tablename");
 
-                            buffer_fadd(select_buf, " oils_i18n_xlate('%s', '%s', '%s', '%s', \"%s\".%s::TEXT, '%s') AS \"%s\"", tname, cname, fname, pkey, cname, pkey, locale, __alias);
+                            buffer_fadd(select_buf, " oils_i18n_xlate('%s', '%s', '%s', '%s', \"%s\".%s::TEXT, '%s') AS \"%s\"", tname, cname, __column, pkey, cname, pkey, locale, __column);
                         } else {
-                                               buffer_fadd(select_buf, " \"%s\".%s AS \"%s\"", cname, fname, __alias);
+                                           buffer_fadd(select_buf, " \"%s\".%s AS \"%s\"", cname, __column, __column);
                         }
                     } else {
-                                           buffer_fadd(select_buf, " \"%s\".%s AS \"%s\"", cname, fname, __alias);
+                                       buffer_fadd(select_buf, " \"%s\".%s AS \"%s\"", cname, __column, __column);
                     }
-                               }
-                       }
-
-                       if (is_agg->size || (flags & SELECT_DISTINCT)) {
 
-                               if (!jsonBoolIsTrue( jsonObjectGetKey( selfield, "aggregate" ) )) {
-                                       if (gfirst) {
-                                               gfirst = 0;
-                                       } else {
-                                               buffer_add(group_buf, ",");
-                                       }
-
-                                       buffer_fadd(group_buf, " %d", sel_pos);
-                               /*
-                               } else if (is_agg = jsonObjectGetKey( selfield, "having" )) {
-                                       if (gfirst) {
-                                               gfirst = 0;
-                                       } else {
-                                               buffer_add(group_buf, ",");
-                                       }
-
-                                       __column = searchFieldTransform(cname, field, selfield);
-                                       buffer_fadd(group_buf, " %s", __column);
-                                       __column = searchFieldTransform(cname, field, selfield);
-                               */
-                               }
-                       }
-
-                       if (__column) free(__column);
-                       if (__alias) free(__alias);
-
-                       sel_pos++;
-               }
-
-        // jsonIteratorFree(select_itr);
-       }
-
-    // jsonIteratorFree(selclass_itr);
+                           // ... but it could be an object, in which case we check for a Field Transform
+                           } else {
+
+                                   __column = jsonObjectToSimpleString( jsonObjectGetKeyConst( selfield, "column" ) );
+
+                                   // again, just to be safe
+                                   osrfHash* field = osrfHashGet( osrfHashGet( idlClass, "fields" ), __column );
+                                   if (!field) continue;
+                                   const char* fname = osrfHashGet(field, "name");
+
+                                   if (first) {
+                                           first = 0;
+                                   } else {
+                                           buffer_add(select_buf, ",");
+                                   }
+
+                                   if ((tmp_const = jsonObjectGetKeyConst( selfield, "alias" ))) {
+                                           __alias = jsonObjectToSimpleString( tmp_const );
+                                   } else {
+                                           __alias = strdup(__column);
+                                   }
+
+                                   if (jsonObjectGetKeyConst( selfield, "transform" )) {
+                                           free(__column);
+                                           __column = searchFieldTransform(cname, field, selfield);
+                                           buffer_fadd(select_buf, " %s AS \"%s\"", __column, __alias);
+                                   } else {
+                        if (locale) {
+                                   char* i18n = osrfHashGet(field, "i18n");
+                                       if (flags & DISABLE_I18N)
+                                i18n = NULL;
+    
+                                   if ( i18n && !strncasecmp("true", i18n, 4)) {
+                                   char* pkey = osrfHashGet(idlClass, "primarykey");
+                                   char* tname = osrfHashGet(idlClass, "tablename");
+
+                                buffer_fadd(select_buf, " oils_i18n_xlate('%s', '%s', '%s', '%s', \"%s\".%s::TEXT, '%s') AS \"%s\"", tname, cname, fname, pkey, cname, pkey, locale, __alias);
+                            } else {
+                                                   buffer_fadd(select_buf, " \"%s\".%s AS \"%s\"", cname, fname, __alias);
+                            }
+                        } else {
+                                               buffer_fadd(select_buf, " \"%s\".%s AS \"%s\"", cname, fname, __alias);
+                        }
+                                   }
+                           }
+
+                           if (is_agg->size || (flags & SELECT_DISTINCT)) {
+
+                                   if (!jsonBoolIsTrue( jsonObjectGetKey( selfield, "aggregate" ) )) {
+                                           if (gfirst) {
+                                                   gfirst = 0;
+                                           } else {
+                                                   buffer_add(group_buf, ",");
+                                           }
+
+                                           buffer_fadd(group_buf, " %d", sel_pos);
+                                   /*
+                                   } else if (is_agg = jsonObjectGetKey( selfield, "having" )) {
+                                           if (gfirst) {
+                                                   gfirst = 0;
+                                           } else {
+                                                   buffer_add(group_buf, ",");
+                                           }
+
+                                           __column = searchFieldTransform(cname, field, selfield);
+                                           buffer_fadd(group_buf, " %s", __column);
+                                           __column = searchFieldTransform(cname, field, selfield);
+                                   */
+                                   }
+                           }
+
+                           if (__column) free(__column);
+                           if (__alias) free(__alias);
+
+                           sel_pos++;
+                   }
+
+            // jsonIteratorFree(select_itr);
+           }
+
+        // jsonIteratorFree(selclass_itr);
+
+           if (is_agg) jsonObjectFree(is_agg);
+    } else {
+        buffer_add(select_buf, "*");
+    }
 
-       if (is_agg) jsonObjectFree(is_agg);
 
        char* col_list = buffer_release(select_buf);
-       char* table = getSourceDefinition(core_meta);
+       char* table = NULL;
+    if (!from_function) table = getSourceDefinition(core_meta);
+    else table = searchValueTransform(join_hash);
 
        // Put it all together
        buffer_fadd(sql_buf, "SELECT %s FROM %s AS \"%s\" ", col_list, table, core_class );
        free(col_list);
        free(table);
 
-       // Now, walk the join tree and add that clause
-       if ( join_hash ) {
-               char* join_clause = searchJOIN( join_hash, core_meta );
-               buffer_add(sql_buf, join_clause);
-               free(join_clause);
-       }
-
-       if ( search_hash ) {
-               buffer_add(sql_buf, " WHERE ");
-
-               // and it's on the the WHERE clause
-               char* pred = searchWHERE( search_hash, core_meta, AND_OP_JOIN );
+    if (!from_function) {
+           // Now, walk the join tree and add that clause
+           if ( join_hash ) {
+                   char* join_clause = searchJOIN( join_hash, core_meta );
+                   buffer_add(sql_buf, join_clause);
+                   free(join_clause);
+           }
+
+           if ( search_hash ) {
+                   buffer_add(sql_buf, " WHERE ");
+
+                   // and it's on the the WHERE clause
+                   char* pred = searchWHERE( search_hash, core_meta, AND_OP_JOIN );
+
+                   if (!pred) {
+                           osrfAppSessionStatus(
+                                   ctx->session,
+                                   OSRF_STATUS_INTERNALSERVERERROR,
+                                   "osrfMethodException",
+                                   ctx->request,
+                                   "Severe query error in WHERE predicate -- see error log for more details"
+                           );
+                           free(core_class);
+                           buffer_free(having_buf);
+                           buffer_free(group_buf);
+                           buffer_free(order_buf);
+                           buffer_free(sql_buf);
+                           if (defaultselhash) jsonObjectFree(defaultselhash);
+                           return NULL;
+                   } else {
+                           buffer_add(sql_buf, pred);
+                           free(pred);
+                   }
+        }
 
-               if (!pred) {
-                       osrfAppSessionStatus(
-                               ctx->session,
-                               OSRF_STATUS_INTERNALSERVERERROR,
-                               "osrfMethodException",
-                               ctx->request,
-                               "Severe query error in WHERE predicate -- see error log for more details"
-                       );
-                       free(core_class);
-                       buffer_free(having_buf);
-                       buffer_free(group_buf);
-                       buffer_free(order_buf);
-                       buffer_free(sql_buf);
-                       if (defaultselhash) jsonObjectFree(defaultselhash);
-                       return NULL;
-               } else {
-                       buffer_add(sql_buf, pred);
-                       free(pred);
-               }
+           if ( having_hash ) {
+                   buffer_add(sql_buf, " HAVING ");
+
+                   // and it's on the the WHERE clause
+                   char* pred = searchWHERE( having_hash, core_meta, AND_OP_JOIN );
+
+                   if (!pred) {
+                           osrfAppSessionStatus(
+                                   ctx->session,
+                                   OSRF_STATUS_INTERNALSERVERERROR,
+                                   "osrfMethodException",
+                                   ctx->request,
+                                   "Severe query error in HAVING predicate -- see error log for more details"
+                           );
+                           free(core_class);
+                           buffer_free(having_buf);
+                           buffer_free(group_buf);
+                           buffer_free(order_buf);
+                           buffer_free(sql_buf);
+                           if (defaultselhash) jsonObjectFree(defaultselhash);
+                           return NULL;
+                   } else {
+                           buffer_add(sql_buf, pred);
+                           free(pred);
+                   }
+           }
+
+           first = 1;
+           jsonIterator* class_itr = jsonNewIterator( order_hash );
+           while ( (snode = jsonIteratorNext( class_itr )) ) {
+
+                   if (!jsonObjectGetKeyConst(selhash,class_itr->key))
+                           continue;
+
+                   if ( snode->type == JSON_HASH ) {
+
+                       jsonIterator* order_itr = jsonNewIterator( snode );
+                           while ( (onode = jsonIteratorNext( order_itr )) ) {
+
+                                   if (!oilsIDLFindPath( "/%s/fields/%s", class_itr->key, order_itr->key ))
+                                           continue;
+
+                                   char* direction = NULL;
+                                   if ( onode->type == JSON_HASH ) {
+                                           if ( jsonObjectGetKeyConst( onode, "transform" ) ) {
+                                                   string = searchFieldTransform(
+                                                           class_itr->key,
+                                                           oilsIDLFindPath( "/%s/fields/%s", class_itr->key, order_itr->key ),
+                                                           onode
+                                                   );
+                                           } else {
+                                                   growing_buffer* field_buf = buffer_init(16);
+                                                   buffer_fadd(field_buf, "\"%s\".%s", class_itr->key, order_itr->key);
+                                                   string = buffer_release(field_buf);
+                                           }
+
+                                           if ( (tmp_const = jsonObjectGetKeyConst( onode, "direction" )) ) {
+                                                   direction = jsonObjectToSimpleString(tmp_const);
+                                                   if (!strncasecmp(direction, "d", 1)) {
+                                                           free(direction);
+                                                           direction = " DESC";
+                                                   } else {
+                                                           free(direction);
+                                                           direction = " ASC";
+                                                   }
+                                           }
+
+                                   } else {
+                                           string = strdup(order_itr->key);
+                                           direction = jsonObjectToSimpleString(onode);
+                                           if (!strncasecmp(direction, "d", 1)) {
+                                                   free(direction);
+                                                   direction = " DESC";
+                                           } else {
+                                                   free(direction);
+                                                   direction = " ASC";
+                                           }
+                                   }
+
+                                   if (first) {
+                                           first = 0;
+                                   } else {
+                                           buffer_add(order_buf, ", ");
+                                   }
+
+                                   buffer_add(order_buf, string);
+                                   free(string);
+
+                                   if (direction) {
+                                           buffer_add(order_buf, direction);
+                                   }
+
+                           }
+                // jsonIteratorFree(order_itr);
+
+                   } else if ( snode->type == JSON_ARRAY ) {
+
+                       jsonIterator* order_itr = jsonNewIterator( snode );
+                           while ( (onode = jsonIteratorNext( order_itr )) ) {
+
+                                   char* _f = jsonObjectToSimpleString( onode );
+
+                                   if (!oilsIDLFindPath( "/%s/fields/%s", class_itr->key, _f))
+                                           continue;
+
+                                   if (first) {
+                                           first = 0;
+                                   } else {
+                                           buffer_add(order_buf, ", ");
+                                   }
+
+                                   buffer_add(order_buf, _f);
+                                   free(_f);
+
+                           }
+                // jsonIteratorFree(order_itr);
+
+
+                   // IT'S THE OOOOOOOOOOOLD STYLE!
+                   } else {
+                           osrfLogError(OSRF_LOG_MARK, "%s: Possible SQL injection attempt; direct order by is not allowed", MODULENAME);
+                           osrfAppSessionStatus(
+                                   ctx->session,
+                                   OSRF_STATUS_INTERNALSERVERERROR,
+                                   "osrfMethodException",
+                                   ctx->request,
+                                   "Severe query error -- see error log for more details"
+                           );
+
+                           free(core_class);
+                           buffer_free(having_buf);
+                           buffer_free(group_buf);
+                           buffer_free(order_buf);
+                           buffer_free(sql_buf);
+                           if (defaultselhash) jsonObjectFree(defaultselhash);
+                           jsonIteratorFree(class_itr);
+                           return NULL;
+                   }
+
+           }
     }
 
-       if ( having_hash ) {
-               buffer_add(sql_buf, " HAVING ");
-
-               // and it's on the the WHERE clause
-               char* pred = searchWHERE( having_hash, core_meta, AND_OP_JOIN );
-
-               if (!pred) {
-                       osrfAppSessionStatus(
-                               ctx->session,
-                               OSRF_STATUS_INTERNALSERVERERROR,
-                               "osrfMethodException",
-                               ctx->request,
-                               "Severe query error in HAVING predicate -- see error log for more details"
-                       );
-                       free(core_class);
-                       buffer_free(having_buf);
-                       buffer_free(group_buf);
-                       buffer_free(order_buf);
-                       buffer_free(sql_buf);
-                       if (defaultselhash) jsonObjectFree(defaultselhash);
-                       return NULL;
-               } else {
-                       buffer_add(sql_buf, pred);
-                       free(pred);
-               }
-       }
-
-       first = 1;
-       jsonIterator* class_itr = jsonNewIterator( order_hash );
-       while ( (snode = jsonIteratorNext( class_itr )) ) {
-
-               if (!jsonObjectGetKeyConst(selhash,class_itr->key))
-                       continue;
-
-               if ( snode->type == JSON_HASH ) {
-
-                   jsonIterator* order_itr = jsonNewIterator( snode );
-                       while ( (onode = jsonIteratorNext( order_itr )) ) {
-
-                               if (!oilsIDLFindPath( "/%s/fields/%s", class_itr->key, order_itr->key ))
-                                       continue;
-
-                               char* direction = NULL;
-                               if ( onode->type == JSON_HASH ) {
-                                       if ( jsonObjectGetKeyConst( onode, "transform" ) ) {
-                                               string = searchFieldTransform(
-                                                       class_itr->key,
-                                                       oilsIDLFindPath( "/%s/fields/%s", class_itr->key, order_itr->key ),
-                                                       onode
-                                               );
-                                       } else {
-                                               growing_buffer* field_buf = buffer_init(16);
-                                               buffer_fadd(field_buf, "\"%s\".%s", class_itr->key, order_itr->key);
-                                               string = buffer_release(field_buf);
-                                       }
-
-                                       if ( (tmp_const = jsonObjectGetKeyConst( onode, "direction" )) ) {
-                                               direction = jsonObjectToSimpleString(tmp_const);
-                                               if (!strncasecmp(direction, "d", 1)) {
-                                                       free(direction);
-                                                       direction = " DESC";
-                                               } else {
-                                                       free(direction);
-                                                       direction = " ASC";
-                                               }
-                                       }
-
-                               } else {
-                                       string = strdup(order_itr->key);
-                                       direction = jsonObjectToSimpleString(onode);
-                                       if (!strncasecmp(direction, "d", 1)) {
-                                               free(direction);
-                                               direction = " DESC";
-                                       } else {
-                                               free(direction);
-                                               direction = " ASC";
-                                       }
-                               }
-
-                               if (first) {
-                                       first = 0;
-                               } else {
-                                       buffer_add(order_buf, ", ");
-                               }
-
-                               buffer_add(order_buf, string);
-                               free(string);
-
-                               if (direction) {
-                                       buffer_add(order_buf, direction);
-                               }
-
-                       }
-            // jsonIteratorFree(order_itr);
-
-               } else if ( snode->type == JSON_ARRAY ) {
-
-                   jsonIterator* order_itr = jsonNewIterator( snode );
-                       while ( (onode = jsonIteratorNext( order_itr )) ) {
-
-                               char* _f = jsonObjectToSimpleString( onode );
-
-                               if (!oilsIDLFindPath( "/%s/fields/%s", class_itr->key, _f))
-                                       continue;
-
-                               if (first) {
-                                       first = 0;
-                               } else {
-                                       buffer_add(order_buf, ", ");
-                               }
-
-                               buffer_add(order_buf, _f);
-                               free(_f);
-
-                       }
-            // jsonIteratorFree(order_itr);
-
-
-               // IT'S THE OOOOOOOOOOOLD STYLE!
-               } else {
-                       osrfLogError(OSRF_LOG_MARK, "%s: Possible SQL injection attempt; direct order by is not allowed", MODULENAME);
-                       osrfAppSessionStatus(
-                               ctx->session,
-                               OSRF_STATUS_INTERNALSERVERERROR,
-                               "osrfMethodException",
-                               ctx->request,
-                               "Severe query error -- see error log for more details"
-                       );
-
-                       free(core_class);
-                       buffer_free(having_buf);
-                       buffer_free(group_buf);
-                       buffer_free(order_buf);
-                       buffer_free(sql_buf);
-                       if (defaultselhash) jsonObjectFree(defaultselhash);
-                       jsonIteratorFree(class_itr);
-                       return NULL;
-               }
-
-       }
-
     // jsonIteratorFree(class_itr);
 
        string = buffer_release(group_buf);
index 9cf011e..daee2c9 100644 (file)
@@ -1088,12 +1088,16 @@ sub biblio_descriptor {
        my $res = $rd_script->run || ($log->error( "Descriptor script died!  $@" ) && return undef);
        $log->debug("Script for biblio descriptor extraction completed successfully");
 
-    if ($res->{date1} ne '    ') {
-        $res->{date1} =~ tr/ux/00/;
+    my $d1 = $res->date1;
+    if ($d1 && $d1 ne '    ') {
+        $d1 =~ tr/ux/00/;
+        $res->date1( $d1 );
     }
 
-    if ($res->{date2} ne '    ') {
-        $res->{date2} =~ tr/ux/99/;
+    my $d2 = $res->date2;
+    if ($d2 && $d2 ne '    ') {
+        $d2 =~ tr/ux/99/;
+        $res->date2( $d2 );
     }
 
        return $res;
index e33e31e..674fea1 100644 (file)
@@ -289,7 +289,7 @@ sub request {
        my $err;
        my $argstr = __arg_to_string( (scalar(@params)) == 1 ? $params[0] : \@params);
 
-       $self->log(I, "request $method $argstr");
+       $self->log(I, "request $method $argstr");
 
        if( ($self->{xact} or $always_xact) and 
                        $self->session->state != OpenSRF::AppSession::CONNECTED() ) {
index 6fa48a5..10080de 100644 (file)
@@ -1,6 +1,8 @@
 package OpenILS::Utils::ZClient;
 use UNIVERSAL::require;
 
+sub DESTROY {};
+
 use overload 'bool' => sub { return $_[0]->{connection} ? 1 : 0 };
 
 sub EVENT_NONE { 0 }
@@ -85,6 +87,7 @@ sub AUTOLOAD {
 #-------------------------------------------------------------------------------
 package OpenILS::Utils::ZClient::ResultSet;
 
+sub DESTROY {};
 our $AUTOLOAD;
 
 sub new {
@@ -128,6 +131,7 @@ sub AUTOLOAD {
 #-------------------------------------------------------------------------------
 package OpenILS::Utils::ZClient::Record;
 
+sub DESTROY {};
 our $AUTOLOAD;
 
 sub new {
index 9e04a78..d6dc8f1 100755 (executable)
@@ -12,6 +12,7 @@ use OpenSRF::System;
 
 my $config = shift || die "bootstrap config required\n";
 my $lockfile = shift || "/tmp/generate_fines-LOCK";
+my $grace = int(shift()) || 1;
 
 if (-e $lockfile) {
         open(F,$lockfile);
@@ -36,7 +37,7 @@ OpenSRF::System->bootstrap_client( config_file => $config );
 
 my $r = OpenSRF::AppSession
                ->create( 'open-ils.storage' )
-               ->request( 'open-ils.storage.action.circulation.overdue.generate_fines' => 1 );
+               ->request( 'open-ils.storage.action.circulation.overdue.generate_fines' => $grace );
 
 while (!$r->complete) { $r->recv };
 
index b8ed0ca..ae1b8d6 100755 (executable)
@@ -17,7 +17,7 @@ my ($config, $org_id, $user_id, $copy_id, $copy_barcode) =
     ('/openils/conf/opensrf_core.xml', 326, 3, 301313, undef);
 
 GetOptions(
-    'org=o' => \$org_id,
+    'org=i' => \$org_id,
     'user=i' => \$user_id,
     'copy=i' => \$copy_id,
     'barcode=s' => \$copy_barcode,
@@ -32,6 +32,7 @@ my $CIRC_TEST = {
             column => 'id',
             params => [$copy_id, $user_id],
             result_field => 'matchpoint',
+            alias => 'matchpoint'
         }]
     },
     from => 'aou',
@@ -40,41 +41,45 @@ my $CIRC_TEST = {
 
 my $e = new_editor();
 
-my $mp_id = $e->json_query($CIRC_TEST)->[0]->{id};
-my $mp = $e->retrieve_config_circ_matrix_ruleset([
-    $mp_id,
+my $start = time;
+my $mp_id = $e->json_query($CIRC_TEST)->[0]->{matchpoint};
+
+my $rule_set = $e->search_config_circ_matrix_ruleset([
+    {matchpoint => $mp_id},
     {   flesh => 1,
         flesh_fields => {
             'ccmrs' => ['duration_rule', 'recurring_fine_rule', 'max_fine_rule']
         }
     }
-]);
+])->[0];
+
+my $rundur = time - $start;
 
 my $cp = $e->retrieve_asset_copy($copy_id);
 my ($dur, $recf);
 
 # get the actual duration
 if($cp->loan_duration == 1) {
-    $dur = $mp->duration_rule->shrt;
+    $dur = $rule_set->duration_rule->shrt;
 } elsif($cp->loan_duration == 2) {
-    $dur = $mp->duration_rule->normal;
+    $dur = $rule_set->duration_rule->normal;
 } else {
-    $dur = $mp->duration_rule->extended;
+    $dur = $rule_set->duration_rule->extended;
 }
 
 # get the recurring fine level
 if($cp->fine_level == 1) {
-    $recf = $mp->recurring_fine_rule->low;
+    $recf = $rule_set->recurring_fine_rule->low;
 } elsif($cp->fine_level == 2) {
-    $recf = $mp->recurring_fine_rule->normal;
+    $recf = $rule_set->recurring_fine_rule->normal;
 } else {
-    $recf = $mp->recurring_fine_rule->high;
+    $recf = $rule_set->recurring_fine_rule->high;
 }
 
-
-print "Duration [".$mp->duration_rule->name."] = $dur\n";
-print "Recurring fines [".$mp->recurring_fine_rule->name."; interval='".
-    $mp->recurring_fine_rule->recurance_interval."'] = \$$recf\n";
-print "Max fine [".$mp->max_fine_rule->name."] = \$".$mp->max_fine_rule->amount."\n";
+print "Duration [".$rule_set->duration_rule->name."] = $dur\n";
+print "Recurring fines [".$rule_set->recurring_fine_rule->name."; interval='".
+    $rule_set->recurring_fine_rule->recurance_interval."'] = \$$recf\n";
+print "Max fine [".$rule_set->max_fine_rule->name."] = \$".$rule_set->max_fine_rule->amount."\n";
+print "took: $rundur\n";
 
 
index e65dcb3..d927fa6 100644 (file)
@@ -82,9 +82,9 @@ if(!dojo._hasResource["fieldmapper.OrgUtils"]){
                                continue;
                        }
 
-                       var parent = fieldmapper.aou.findOrgUnit(x.parent_ou(),true);
-                       if (!parent.children()) parent.children([]);
-                       parent.children().push(x);
+                       var par = fieldmapper.aou.findOrgUnit(x.parent_ou(),true);
+                       if (!par.children()) par.children([]);
+                       par.children().push(x);
                        fieldmapper.aou.OrgCache[x.id()].treePtr = x;
                }
 
index 2acf826..b23fb62 100644 (file)
@@ -112,9 +112,9 @@ for (var i in orgArraySearcher) {
                continue;
        } 
 
-       var parent = findOrgUnit(x.parent_ou());
-       if (!parent.children()) parent.children(new Array());
-       parent.children().push(x);
+       var par = findOrgUnit(x.parent_ou());
+       if (!par.children()) par.children(new Array());
+       par.children().push(x);
 }
 
 function _tree_killer () {
index b7aa882..3064574 100644 (file)
@@ -81,6 +81,15 @@ body { font-size: 12pt; }
     display: block;
     visibility: visible;
 }
+#selfck-items-out-done-div {
+    width: 100%;
+    text-align: center;
+    margin-top: 20px;
+}
 
+.selfck-done-link {
+    font-size: 12pt;
+    font-weight: bold;
+}
 
 
index 3ac63e0..e723aad 100644 (file)
 ----------------------------------------------------------------- */
 
 var STAFF_SES_PARAM = 'ses';
+var PATRON_BARCODE_COOKIE = 'pbcc';
 var patron = null
 var itemBarcode = null;
 var itemsOutTemplate = null;
 var isRenewal = false;
 var pendingXact = false;
-var patronTimeout = 120000;
+var patronTimeout = 600000; /* 10 minutes */
 var timerId = null;
 var printWrapper;
 var printTemplate;
 var successfulItems = {};
+var scanTimeout = 800;
+var scanTimeoutId;
+var patronBarcodeRegex;
 
 
 function selfckInit() {
     var cgi = new CGI();
     var staff = grabUser(cookieManager.read(STAFF_SES_PARAM) || cgi.param(STAFF_SES_PARAM));
 
+    selfckSetupPrinter();
+
     /*
     XXX we need org information (from the proxy?)
     var t = fetchOrgSettingDefault(1, 'circ.selfcheck.patron_login_timeout');
     patronTimeout = (t) ? parseInt(t) * 1000 : patronTimeout;
     */
 
+    var reg = fetchOrgSettingDefault(globalOrgTree.id(), 'opac.barcode_regex');
+    if(reg) patronBarcodeRegex = new RegExp(reg);
+
     if(!staff) {
         // should not happen when behind the proxy
         return alert('Staff must login');
@@ -54,10 +63,7 @@ function selfckInit() {
             selfckPatronLogin();
     };
 
-    $('selfck-item-barcode-input').onkeypress = function(evt) {
-        if(userPressedEnter(evt)) 
-            selfckCheckout();
-    };
+    $('selfck-item-barcode-input').onkeypress = selfckItemBarcodeKeypress;
 
     // for debugging, allow passing the user barcode via param
     var urlbc = new CGI().param('patron');
@@ -70,7 +76,55 @@ function selfckInit() {
     printTemplate = printWrapper.removeChild($n(printWrapper, 'selfck-print-items-template'));
     itemsOutTemplate = $('selfck-items-out-tbody').removeChild($('selfck-items-out-row'));
 
+    selfckTryPatronCookie();
+
 //    selfckMkDummyCirc(); // testing only
+    
+}
+
+function selfckSetupPrinter() {
+    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) {
+        
+    }
+}
+
+function selfckTryPatronCookie() {
+    var pb = cookieManager.read(PATRON_BARCODE_COOKIE);
+    if(pb) {
+        cookieManager.write(PATRON_BARCODE_COOKIE, '');
+        $('selfck-patron-login-input').value = pb;
+        selfckPatronLogin();
+    }
+}
+
+
+function selfckItemBarcodeKeypress(evt) {
+    if(userPressedEnter(evt)) {
+        clearTimeout(scanTimeoutId);
+        selfckCheckout();
+    } else {
+        /*  If scanTimeout milliseconds have passed and there is
+            still data in the input box, it's a likely indication
+            of a partial scan. Select the text so the next scan
+            will replace the value */
+        clearTimeout(scanTimeoutId);
+        scanTimeoutId = setTimeout(
+            function() {
+                if($('selfck-item-barcode-input').value) {
+                    $('selfck-item-barcode-input').select();
+                }
+            },
+            scanTimeout
+        );
+    }
 }
 
 /*
@@ -100,8 +154,13 @@ function selfckResetTimer() {
 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;
+    if(patron) {
+        selfckPrint();
+        setTimeout(
+            function() { location.href = location.href; },
+            800
+        );
+    }
 }
 
 /*
@@ -139,6 +198,21 @@ function selfckPatronLogin(barcode) {
 }
 
 /**
+  * If a user barcode was scanned into the item barcode
+  * input, log out the current user and log in the new user
+  */
+function selfckCheckPatronBarcode(itemBc) {
+    if(patronBarcodeRegex) {
+        if(itemBc.match(patronBarcodeRegex)) {
+            cookieManager.write(PATRON_BARCODE_COOKIE, itemBc, -1);
+            selfckLogoutPatron();
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
   * Sends the checkout request
   */
 function selfckCheckout() {
@@ -153,6 +227,9 @@ function selfckCheckout() {
     itemBarcode = $('selfck-item-barcode-input').value;
     if(!itemBarcode) return;
 
+    if(selfckCheckPatronBarcode(itemBarcode))
+        return;
+
     if (itemBarcode in successfulItems) {
         selfckShowMsgNode({textcode:'dupe-barcode'});
         $('selfck-item-barcode-input').select();
@@ -210,7 +287,7 @@ function selfckShowMsgNode(evt) {
   * Renders a row in the checkouts table for the current circulation
   */
 function selfckDislplayCheckout(evt) {
-    unHideMe($('selfck-items-out-table'));
+    unHideMe($('selfck-items-out-table-wrapper'));
 
     var template = itemsOutTemplate.cloneNode(true);
     var copy = evt.payload.copy;
@@ -279,8 +356,11 @@ function selfckRenew() {
   * Sets the print date and prints the page
   */
 function selfckPrint() {
-    appendClear($('selfck-print-date'), text(new Date().toLocaleString()));
-    window.print();
+    for(var x in successfulItems) { // make sure we've checked out at least one item
+        appendClear($('selfck-print-date'), text(new Date().toLocaleString()));
+        window.print();
+        return;
+    }
 }
 
 
index b2a98dc..4337899 100644 (file)
                     </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>
+                            <a href='javascript:void(0);' class='selfck-done-link' 
+                                onclick='selfckLogoutPatron();'>&selfck.done;</a>
                         </span>
                     </div>
                 </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>
+                            <span><button onclick='$("selfck-item-barcode-input").value = "";'>&selfck.clear;</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 id='selfck-items-out-table-wrapper' class='hide_me'>
+                    <table id='selfck-items-out-table'>
+                        <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 id='selfck-items-out-done-div'>
+                        <a href='javascript:void(0);' id='selfck-print-co-button' 
+                            class='selfck-done-link' onclick='selfckLogoutPatron();'>&selfck.done;</a>
+                    </div>
+                </div>
             </div>
         </div>
 
index c493fbb..0ef11d9 100644 (file)
@@ -645,6 +645,7 @@ Ensure Caps-Lock is off and try again or contact your local library.">
 <!ENTITY selfck.staff_login "Library barcode or username">
 <!ENTITY selfck.staff_pw "Password">
 <!ENTITY selfck.submit "Submit">
+<!ENTITY selfck.clear "Clear">
 <!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">
@@ -655,8 +656,7 @@ Ensure Caps-Lock is off and try again or contact your local library.">
 <!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.done "Done">
 <!ENTITY selfck.welcome "Welcome">
 
 <!-- event messages -->
@@ -666,5 +666,4 @@ Ensure Caps-Lock is off and try again or contact your local library.">
 <!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 14c83e2..a3a4fdc 100644 (file)
@@ -349,7 +349,7 @@ function myOPACDrawHolds(r) {
             unHideMe($n(row, 'myopac_hold_unfrozen_false'))
             if(h.thaw_date()) {
                 var d = dojo.date.stamp.fromISOString(h.thaw_date());
-                $n(row, 'myopac_holds_frozen_until').appendChild(text(dojo.date.locale.format(d, {.selector: 'date', fullYear: true})));
+                $n(row, 'myopac_holds_frozen_until').appendChild(text(dojo.date.locale.format(d, {selector: 'date', fullYear: true})));
             }
         } else {
             unHideMe($n(row, 'myopac_hold_unfrozen_true'))