Merge branch 'opac-tt-poc' of git+ssh://yeti.esilibrary.com/home/evergreen/evergreen...
authorMike Rylander <mrylander@gmail.com>
Wed, 27 Apr 2011 01:15:37 +0000 (21:15 -0400)
committerMike Rylander <mrylander@gmail.com>
Wed, 27 Apr 2011 01:15:37 +0000 (21:15 -0400)
29 files changed:
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/QueryParser.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/AddedContent/OpenLibrary.pm
Open-ILS/src/sql/Pg/002.schema.config.sql
Open-ILS/src/sql/Pg/030.schema.metabib.sql
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/0524.data.toggle_unified_volume_copy_editor.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/0525.schema.phys-char-regression.sql [new file with mode: 0644]
Open-ILS/src/support-scripts/authority_control_fields.pl
Open-ILS/web/js/dojo/openils/actor/nls/register.js
Open-ILS/web/js/ui/default/actor/user/register.js
Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/web/opac/skin/default/css/layout.css
Open-ILS/web/opac/skin/default/js/myopac.js
Open-ILS/web/templates/default/actor/user/register.tt2
Open-ILS/web/templates/default/actor/user/register_table.tt2
Open-ILS/xul/staff_client/chrome/content/cat/opac.js
Open-ILS/xul/staff_client/chrome/content/main/menu.js
Open-ILS/xul/staff_client/chrome/content/util/print.js
Open-ILS/xul/staff_client/server/admin/printer_settings.js
Open-ILS/xul/staff_client/server/cat/bib_brief.js
Open-ILS/xul/staff_client/server/cat/copy_browser.js
Open-ILS/xul/staff_client/server/cat/volume_copy_creator.js
Open-ILS/xul/staff_client/server/circ/checkin.js
Open-ILS/xul/staff_client/server/circ/checkin_overlay.xul
Open-ILS/xul/staff_client/server/circ/copy_status.js
Open-ILS/xul/staff_client/server/circ/util.js
Open-ILS/xul/staff_client/server/patron/holds.js
build/i18n/po/register.js/register.js.pot

index 1915424..b858fd5 100644 (file)
@@ -585,6 +585,13 @@ sub toSQL {
 
     my $core_limit = $self->QueryParser->core_limit || 25000;
 
+    my $flat_where = $$flat_plan{where};
+    if ($flat_where eq '()') {
+        $flat_where = '';
+    } else {
+        $flat_where = "AND $flat_where";
+    }
+
     my $sql = <<SQL;
 SELECT  $key AS id,
         ARRAY_ACCUM(DISTINCT m.source) AS records,
@@ -600,7 +607,7 @@ SELECT  $key AS id,
         $during
         $between
         $combined_dyn_filters
-        AND $$flat_plan{where}
+        $flat_where
   GROUP BY 1
   ORDER BY 4 $desc NULLS LAST, 5 DESC NULLS LAST, 3 DESC
   LIMIT $core_limit
index 52a203b..1b3a37f 100644 (file)
@@ -546,7 +546,7 @@ sub decompose {
             warn "Encountered explicit group end\n" if $self->debug;
 
             $_ = $';
-            $remainder = $';
+            $remainder = $struct->top_plan ? '' : $';
 
             $last_type = '';
         } elsif ($self->filter_count && /$filter_re/) { # found a filter
@@ -593,7 +593,7 @@ sub decompose {
             warn "Encountered explicit group start\n" if $self->debug;
 
             my ($substruct, $subremainder) = $self->decompose( $', $current_class, $recursing + 1 );
-            $struct->add_node( $substruct );
+            $struct->add_node( $substruct ) if ($substruct);
             $_ = $subremainder;
 
             $last_type = '';
@@ -685,6 +685,8 @@ sub decompose {
 
     }
 
+    $struct = undef if (scalar(@{$struct->query_nodes}) == 0 && !$struct->top_plan);
+
     return $struct if !wantarray;
     return ($struct, $remainder);
 }
index 634fdc7..fab9ea9 100644 (file)
@@ -114,9 +114,9 @@ sub toc_html {
         my $page_number = $chapter->{pagenum} || '';
  
         $toc_html .= '<tr>' .
-            "<td style='text-align: right;'>$label</td>" .
-            "<td style='text-align: left; padding-right: 2em;'>$title</td>" .
-            "<td style='text-align: right;'>$page_number</td>" .
+            "<td class='toc_label'>$label</td>" .
+            "<td class='toc_title'>$title</td>" .
+            "<td class='toc_page'>$page_number</td>" .
             "</tr>\n";
     }
 
index 5bbb33d..0ca0d89 100644 (file)
@@ -57,7 +57,7 @@ CREATE TABLE config.upgrade_log (
     install_date    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
 );
 
-INSERT INTO config.upgrade_log (version) VALUES ('0523'); -- dbs
+INSERT INTO config.upgrade_log (version) VALUES ('0524'); -- phasefx
 
 CREATE TABLE config.bib_source (
        id              SERIAL  PRIMARY KEY,
index 9e8272f..2f6539f 100644 (file)
@@ -1065,9 +1065,10 @@ BEGIN
                     attr_value := oils_xpath_string(attr_def.xpath, transformed_xml, COALESCE(attr_def.joiner,' '), ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]]);
 
                 ELSIF attr_def.phys_char_sf IS NOT NULL THEN -- a named Physical Characteristic, see config.marc21_physical_characteristic_*_map
-                    SELECT  value::TEXT INTO attr_value
-                      FROM  biblio.marc21_physical_characteristics(NEW.id)
-                      WHERE subfield = attr_def.phys_char_sf
+                    SELECT  m.value INTO attr_value
+                      FROM  biblio.marc21_physical_characteristics(NEW.id) v
+                            JOIN config.marc21_physical_characteristic_value_map m ON (m.id = v.value)
+                      WHERE v.subfield = attr_def.phys_char_sf
                       LIMIT 1; -- Just in case ...
 
                 END IF;
index 011178a..83c8547 100644 (file)
@@ -7984,3 +7984,13 @@ INSERT into config.org_unit_setting_type
   oils_i18n_gettext( 'cat.default_copy_status_normal', 'Default status when a copy is created using the normal volume/copy creator interface.', 'coust', 'description'),
   'link', 'ccs'
 );
+
+-- 0524.data.toggle_unified_volume_copy_editor.sql
+
+INSERT into config.org_unit_setting_type
+( name, label, description, datatype ) VALUES
+( 'ui.unified_volume_copy_editor',
+  oils_i18n_gettext( 'ui.unified_volume_copy_editor', 'GUI: Unified Volume/Item Creator/Editor', 'coust', 'label'),
+  oils_i18n_gettext( 'ui.unified_volume_copy_editor', 'If true combines the Volume/Copy Creator and Item Attribute Editor in some instances.', 'coust', 'description'),
+  'bool'
+);
diff --git a/Open-ILS/src/sql/Pg/upgrade/0524.data.toggle_unified_volume_copy_editor.sql b/Open-ILS/src/sql/Pg/upgrade/0524.data.toggle_unified_volume_copy_editor.sql
new file mode 100644 (file)
index 0000000..994b180
--- /dev/null
@@ -0,0 +1,13 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0524'); -- phasefx
+
+INSERT into config.org_unit_setting_type
+( name, label, description, datatype ) VALUES
+( 'ui.unified_volume_copy_editor',
+  oils_i18n_gettext( 'ui.unified_volume_copy_editor', 'GUI: Unified Volume/Item Creator/Editor', 'coust', 'label'),
+  oils_i18n_gettext( 'ui.unified_volume_copy_editor', 'If true combines the Volume/Copy Creator and Item Attribute Editor in some instances.', 'coust', 'description'),
+  'bool'
+);
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/0525.schema.phys-char-regression.sql b/Open-ILS/src/sql/Pg/upgrade/0525.schema.phys-char-regression.sql
new file mode 100644 (file)
index 0000000..ddbc1f0
--- /dev/null
@@ -0,0 +1,165 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0525'); -- miker
+
+CREATE OR REPLACE FUNCTION biblio.indexing_ingest_or_delete () RETURNS TRIGGER AS $func$
+DECLARE
+    transformed_xml TEXT;
+    prev_xfrm       TEXT;
+    normalizer      RECORD;
+    xfrm            config.xml_transform%ROWTYPE;
+    attr_value      TEXT;
+    new_attrs       HSTORE := ''::HSTORE;
+    attr_def        config.record_attr_definition%ROWTYPE;
+BEGIN
+
+    IF NEW.deleted IS TRUE THEN -- If this bib is deleted
+        DELETE FROM metabib.metarecord_source_map WHERE source = NEW.id; -- Rid ourselves of the search-estimate-killing linkage
+        DELETE FROM metabib.record_attr WHERE id = NEW.id; -- Kill the attrs hash, useless on deleted records
+        DELETE FROM authority.bib_linking WHERE bib = NEW.id; -- Avoid updating fields in bibs that are no longer visible
+        DELETE FROM biblio.peer_bib_copy_map WHERE peer_record = NEW.id; -- Separate any multi-homed items
+        RETURN NEW; -- and we're done
+    END IF;
+
+    IF TG_OP = 'UPDATE' THEN -- re-ingest?
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc' AND enabled;
+
+        IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change
+            RETURN NEW;
+        END IF;
+    END IF;
+
+    -- Record authority linking
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_linking' AND enabled;
+    IF NOT FOUND THEN
+        PERFORM biblio.map_authority_linking( NEW.id, NEW.marc );
+    END IF;
+
+    -- Flatten and insert the mfr data
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_metabib_full_rec' AND enabled;
+    IF NOT FOUND THEN
+        PERFORM metabib.reingest_metabib_full_rec(NEW.id);
+
+        -- Now we pull out attribute data, which is dependent on the mfr for all but XPath-based fields
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_metabib_rec_descriptor' AND enabled;
+        IF NOT FOUND THEN
+            FOR attr_def IN SELECT * FROM config.record_attr_definition ORDER BY format LOOP
+
+                IF attr_def.tag IS NOT NULL THEN -- tag (and optional subfield list) selection
+                    SELECT  ARRAY_TO_STRING(ARRAY_ACCUM(value), COALESCE(attr_def.joiner,' ')) INTO attr_value
+                      FROM  (SELECT * FROM metabib.full_rec ORDER BY tag, subfield) AS x
+                      WHERE record = NEW.id
+                            AND tag LIKE attr_def.tag
+                            AND CASE
+                                WHEN attr_def.sf_list IS NOT NULL 
+                                    THEN POSITION(subfield IN attr_def.sf_list) > 0
+                                ELSE TRUE
+                                END
+                      GROUP BY tag
+                      ORDER BY tag
+                      LIMIT 1;
+
+                ELSIF attr_def.fixed_field IS NOT NULL THEN -- a named fixed field, see config.marc21_ff_pos_map.fixed_field
+                    attr_value := biblio.marc21_extract_fixed_field(NEW.id, attr_def.fixed_field);
+
+                ELSIF attr_def.xpath IS NOT NULL THEN -- and xpath expression
+
+                    SELECT INTO xfrm * FROM config.xml_transform WHERE name = attr_def.format;
+            
+                    -- See if we can skip the XSLT ... it's expensive
+                    IF prev_xfrm IS NULL OR prev_xfrm <> xfrm.name THEN
+                        -- Can't skip the transform
+                        IF xfrm.xslt <> '---' THEN
+                            transformed_xml := oils_xslt_process(NEW.marc,xfrm.xslt);
+                        ELSE
+                            transformed_xml := NEW.marc;
+                        END IF;
+            
+                        prev_xfrm := xfrm.name;
+                    END IF;
+
+                    IF xfrm.name IS NULL THEN
+                        -- just grab the marcxml (empty) transform
+                        SELECT INTO xfrm * FROM config.xml_transform WHERE xslt = '---' LIMIT 1;
+                        prev_xfrm := xfrm.name;
+                    END IF;
+
+                    attr_value := oils_xpath_string(attr_def.xpath, transformed_xml, COALESCE(attr_def.joiner,' '), ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]]);
+
+                ELSIF attr_def.phys_char_sf IS NOT NULL THEN -- a named Physical Characteristic, see config.marc21_physical_characteristic_*_map
+                    SELECT  m.value INTO attr_value
+                      FROM  biblio.marc21_physical_characteristics(NEW.id) v
+                            JOIN config.marc21_physical_characteristic_value_map m ON (m.id = v.value)
+                      WHERE v.subfield = attr_def.phys_char_sf
+                      LIMIT 1; -- Just in case ...
+
+                END IF;
+
+                -- apply index normalizers to attr_value
+                FOR normalizer IN
+                    SELECT  n.func AS func,
+                            n.param_count AS param_count,
+                            m.params AS params
+                      FROM  config.index_normalizer n
+                            JOIN config.record_attr_index_norm_map m ON (m.norm = n.id)
+                      WHERE attr = attr_def.name
+                      ORDER BY m.pos LOOP
+                        EXECUTE 'SELECT ' || normalizer.func || '(' ||
+                            quote_literal( attr_value ) ||
+                            CASE
+                                WHEN normalizer.param_count > 0
+                                    THEN ',' || REPLACE(REPLACE(BTRIM(normalizer.params,'[]'),E'\'',E'\\\''),E'"',E'\'')
+                                    ELSE ''
+                                END ||
+                            ')' INTO attr_value;
+        
+                END LOOP;
+
+                -- Add the new value to the hstore
+                new_attrs := new_attrs || hstore( attr_def.name, attr_value );
+
+            END LOOP;
+
+            IF TG_OP = 'INSERT' OR OLD.deleted THEN -- initial insert OR revivication
+                INSERT INTO metabib.record_attr (id, attrs) VALUES (NEW.id, new_attrs);
+            ELSE
+                UPDATE metabib.record_attr SET attrs = attrs || new_attrs WHERE id = NEW.id;
+            END IF;
+
+        END IF;
+    END IF;
+
+    -- Gather and insert the field entry data
+    PERFORM metabib.reingest_metabib_field_entries(NEW.id);
+
+    -- Located URI magic
+    IF TG_OP = 'INSERT' THEN
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_located_uri' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM biblio.extract_located_uris( NEW.id, NEW.marc, NEW.editor );
+        END IF;
+    ELSE
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_located_uri' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM biblio.extract_located_uris( NEW.id, NEW.marc, NEW.editor );
+        END IF;
+    END IF;
+
+    -- (re)map metarecord-bib linking
+    IF TG_OP = 'INSERT' THEN -- if not deleted and performing an insert, check for the flag
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.metarecord_mapping.skip_on_insert' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
+        END IF;
+    ELSE -- we're doing an update, and we're not deleted, remap
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.metarecord_mapping.skip_on_update' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
+        END IF;
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+COMMIT;
index 1b28a6e..290d036 100755 (executable)
@@ -339,7 +339,7 @@ my %controllees = (
 foreach my $rec_id (@records) {
     # print "$rec_id\n";
 
-    my $e = OpenILS::Utils::CStoreEditor->new(xact=>1);
+    my $e = OpenILS::Utils::CStoreEditor->new();
     # State variable; was the record changed?
     my $changed;
 
@@ -395,6 +395,12 @@ foreach my $rec_id (@records) {
 
             # print Dumper($validates);
 
+            # Protect against failed (error condition) search request
+            if (!$validates) {
+                print STDERR "Search for matching authority failed; record # $rec_id\n";
+                next;
+            }
+
             if (scalar(@$validates) == 0) {
                 next;
             }
@@ -418,6 +424,7 @@ foreach my $rec_id (@records) {
         }
     }
     if ($changed) {
+        my $editor = OpenILS::Utils::CStoreEditor->new(xact=>1);
         # print $marc->as_formatted();
         my $xml = $marc->as_xml_record();
         $xml =~ s/\n//sgo;
@@ -427,9 +434,9 @@ foreach my $rec_id (@records) {
         $xml = OpenILS::Application::AppUtils->entityize($xml);
 
         $record->marc($xml);
-        $e->update_biblio_record_entry($record);
+        $editor->update_biblio_record_entry($record);
+        $editor->commit();
     }
-    $e->commit();
 }
 
 __END__
index ab1150a..b16af89 100644 (file)
@@ -9,5 +9,26 @@
     "DUPE_PATRON_ADDR" : "Found ${0} patron(s) with the same address",
     "REPLACED_ADDRESS" : "<div>Replaces address <b>${0}</b><br/> ${1} ${2}<br/> ${3}, ${4} ${5}</div>",
     "INVALID_FORM" : "Form is invalid.  Please edit and try again.",
-    "EXAMPLE" : "Example: "
+    "EXAMPLE" : "Example: ",
+    "REPLACE_BARCODE" : "Replace Barcode",
+    "BARCODE_IN_USE" : "Barcode is already in use",
+    "SEE_ALL" : "See All",
+    "DUPE_USERNAME" : "Username is already in use",
+    "RESET_PASSWORD" : "Reset Password",
+    "VERIFY_PASSWORD" : "Verify Password",
+    "PARENT_OR_GUARDIAN" : "Parent/Guardian",
+    "USER_SETTINGS" : "User Settings",
+    "ADDRESS_HEADER" : "Address",
+    "ADDRESS_MAILING" : "Mailing",
+    "ADDRESS_BILLING" : "Billing",
+    "ADDRESS_PENDING" : "This is a pending address: ",
+    "ADDRESS_APPROVE" : "Approve Address",
+    "ADDRESS_OWNED" : "This address is owned by another user: ",
+    "ADDRESS_NEW" : "New Address",
+    "STAT_CATS" : "Statistical Categories",
+    "SAVE" : "Save",
+    "SAVE_CLONE" : "Save &amp; Clone",
+    "SHOW_REQUIRED" : "Show Only Required Fields",
+    "SHOW_SUGGESTED" : "Show Suggested Fields",
+    "SHOW_ALL" : "Show All Fields"
 }
index 7154593..f0cad18 100644 (file)
@@ -61,6 +61,29 @@ function load() {
     var userId = cgi.param('usr');
     var stageUname = cgi.param('stage');
 
+    saveButton.attr("label", localeStrings.SAVE);
+    saveCloneButton.attr("label", localeStrings.SAVE_CLONE);
+    replaceBarcode.attr("label", localeStrings.REPLACE_BARCODE);
+    dojo.byId('uedit-show-required').innerHTML = localeStrings.SHOW_REQUIRED;
+    dojo.byId('uedit-show-suggested').innerHTML = localeStrings.SHOW_SUGGESTED;
+    dojo.byId('uedit-show-all').innerHTML = localeStrings.SHOW_ALL;
+    dojo.byId('uedit-dupe-barcode-warning').innerHTML = localeStrings.BARCODE_IN_USE;
+    allCards.attr("label", localeStrings.SEE_ALL);
+    dojo.byId('uedit-dupe-username-warning').innerHTML = localeStrings.DUPE_USERNAME;
+    generatePassword.attr("label", localeStrings.RESET_PASSWORD);
+    dojo.byId('verifyPassword').innerHTML = localeStrings.VERIFY_PASSWORD;
+    dojo.byId('parentGuardian').innerHTML = localeStrings.PARENT_OR_GUARDIAN;
+    dojo.byId('userSettings').innerHTML = localeStrings.USER_SETTINGS;
+    dojo.byId('statCats').innerHTML = localeStrings.STAT_CATS;
+
+    dojo.query("td[name='addressHeader']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_HEADER; });
+    dojo.query("span[name='mailingAddress']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_MAILING; });
+    dojo.query("span[name='billingAddress']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_BILLING; });
+    dojo.query("span[name='addressPending']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_PENDING; });
+    dojo.query("button[name='approve-button']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_APPROVE; });
+    dojo.query("span[name='address-already-owned']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_OWNED; });
+    dojo.query("button[name='addressNew']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_NEW; });
+
     if(xulG) {
            if(xulG.ses) openils.User.authtoken = xulG.ses;
            if(typeof xulG.clone != 'undefined') cloneUser = xulG.clone;
@@ -187,6 +210,8 @@ function load() {
 
     checkGrpAppPerm(); // to do the initial load
     loadStaticFields();
+
+
     if(patron.isnew() && patron.addresses().length == 0) 
         uEditNewAddr(null, uEditAddrVirtId, true);
     else loadAllAddrs();
@@ -1515,7 +1540,7 @@ function uEditNewAddr(evt, id, mkLinks) {
                 }
 
             } else if(row.getAttribute('name') == 'uedit-addr-divider') {
-                // link up the billing/mailing address and give the inputs IDs so we can acces the later
+                // link up the billing/mailing address and give the inputs IDs so we can access the later
                 
                 // billing address
                 var ba = getByName(row, 'billing_address');
index fb7e927..405dcca 100644 (file)
 <!ENTITY staff.circ.checkin_overlay.actions.label "Actions for Selected Items">
 <!ENTITY staff.circ.checkin_overlay.actions.accesskey "S">
 <!ENTITY staff.circ.checkin_overlay.checkin_export.label "Export">
+<!ENTITY staff.circ.checkin_overlay.printer_prompt.label "Printer Prompt">
 <!ENTITY staff.circ.checkin_overlay.trim_list.label "Trim List (20 rows)">
 <!ENTITY staff.circ.checkin_overlay.async_checkin.label "Fast Entry (Asynchronous)">
 <!ENTITY staff.circ.checkin_overlay.strict_barcode.label "Strict Barcode">
 <!ENTITY staff.cat.copy_browser.actions.cmd_create_brt.accesskey "K">
 <!ENTITY staff.cat.copy_browser.actions.sel_patron.label "Show Last Few Circulations">
 <!ENTITY staff.cat.copy_browser.actions.sel_patron.accesskey "L">
-<!ENTITY staff.cat.copy_browser.actions.cmd_edit_items.label "Edit Item Attributes / Call Numbers / Replace Barcodes">
+<!ENTITY staff.cat.copy_browser.actions.cmd_edit_items.label "Edit Items">
 <!ENTITY staff.cat.copy_browser.actions.cmd_edit_items.accesskey "E">
 <!ENTITY staff.cat.copy_browser.actions.cmd_transfer_items.label "Transfer Items to Previously Marked Volume">
 <!ENTITY staff.cat.copy_browser.actions.cmd_transfer_items.accesskey "T">
index 45a2e19..1197a74 100644 (file)
@@ -251,3 +251,8 @@ tr[name="myopac_invalid_addr_row"] td {
     background:#e0e0e0;
     color:red;
 }
+
+/* Table of contents layout */
+td.toc_label { text-align: right; }
+td.toc_title { text-align: left; padding-left: 1em; padding-right: 2em; }
+td.toc_page { text-align: right; }
index 8f136b1..12fbaf1 100644 (file)
@@ -1633,7 +1633,7 @@ function myopacProcessHolds(action, thawDate) {
         switch(action) { 
 
             case 'cancel':
-                req = new Request(CANCEL_HOLD, G.user.session, hold.id());
+                   req = new Request(CANCEL_HOLD, G.user.session, hold.id(), /* Patron via OPAC */ 6);
                 break;
     
             case 'thaw':
index aa1dad5..a821020 100644 (file)
@@ -15,8 +15,8 @@
 </div>
 
 <div id='uedit-save-div'>
-    <button dojoType='dijit.form.Button' jsId='saveButton' onClick='uEditSave' scrollOnFocus='false'>Save</button>
-    <button dojoType='dijit.form.Button' jsId='saveCloneButton' onClick='uEditSaveClone' scrollOnFocus='false'>Save &amp; Clone</button>
+    <button dojoType='dijit.form.Button' jsId='saveButton' onClick='uEditSave' scrollOnFocus='false'></button>
+    <button dojoType='dijit.form.Button' jsId='saveCloneButton' onClick='uEditSaveClone' scrollOnFocus='false'></button>
     <div id='require-toggle'>
         <a href='javascript:uEditToggleRequired(1);' id='uedit-show-required'>Show Only Required Fields</a><br id='uedit-show-required-br'/>
         <a href='javascript:uEditToggleRequired(2);' id='uedit-show-suggested'>Show Suggested Fields</a><br id='uedit-show-suggested-br'/>
index 711e56f..5528252 100644 (file)
@@ -2,30 +2,28 @@
     <tr fmclass='ac' fmfield='barcode' required='required'>
         <td/><td/><td/>
         <td>
-            <button dojoType='dijit.form.Button' jsId='replaceBarcode' scrollOnFocus='false'>Replace Barcode</button>
+            <button dojoType='dijit.form.Button' jsId='replaceBarcode' scrollOnFocus='false'></button>
             <span id='uedit-dupe-barcode-warning' style='color:red; font-weight:bold' class='hidden'>
-                Barcode is already in use
             </span>
         </td>
         <td id='uedit-all-barcodes' class='hidden'>
-            <button dojoType='dijit.form.Button' jsId='allCards' scrollOnFocus='false'>See All</button>
+            <button dojoType='dijit.form.Button' jsId='allCards' scrollOnFocus='false'></button>
         </td>
     </tr>
     <tr fmclass='au' fmfield='usrname' required='required'>
         <td/><td/><td/>
         <td>
             <span id='uedit-dupe-username-warning' style='color:red; font-weight:bold' class='hidden'>
-                Username is already in use
             </span>
         </td>
     </tr>
     <tr fmclass='au' fmfield='passwd' required='required'>
         <td/><td/><td/>
         <td>
-            <button dojoType='dijit.form.Button' jsId='generatePassword' scrollOnFocus='false' tabIndex='-1'>Reset Password</button>
+            <button dojoType='dijit.form.Button' jsId='generatePassword' scrollOnFocus='false' tabIndex='-1'></button>
         </td>
     </tr>
-    <tr fmclass='au' fmfield='passwd2' required='required'><td/><td>Verify Password</td><td/></tr>
+    <tr fmclass='au' fmfield='passwd2' required='required'><td/><td id='verifyPassword'></td><td/></tr>
     <tr fmclass='au' fmfield='first_given_name' required='required'/>
     <tr fmclass='au' fmfield='second_given_name'/>
     <tr fmclass='au' fmfield='family_name' required='required'/>
@@ -35,7 +33,7 @@
     <tr fmclass='au' fmfield='juvenile'/>
     <tr fmclass='au' fmfield='ident_type' required='required'/>
     <tr fmclass='au' fmfield='ident_value'/>
-    <tr fmclass='au' fmfield='ident_value2'><td/><td>Parent/Guardian</td></tr>
+    <tr fmclass='au' fmfield='ident_value2'><td/><td id='parentGuardian'></td></tr>
     <tr fmclass='au' fmfield='email'/>
     <tr fmclass='au' fmfield='day_phone'/>
     <tr fmclass='au' fmfield='evening_phone'/>
@@ -51,7 +49,7 @@
     <tr fmclass='au' fmfield='claims_never_checked_out_count' wclass='dijit.form.NumberSpinner' wconstraints="{min:0,places:0}" wvalue='0'/>
     <tr fmclass='au' fmfield='alert_message' wclass='dijit.form.Textarea' wstyle='height:5em'/>
 
-    <tr class='divider hidden' id='uedit-settings-divider'><td colspan='0'>User Settings</td></tr>
+    <tr class='divider hidden' id='uedit-settings-divider'><td colspan='0' id='userSettings'></td></tr>
     <tr class='hidden' id='uedit-user-setting-template'>
         <td/>
         <td><span name='label'></span></td>
 
     <!-- Address -->
     <tr name='uedit-addr-divider' class='divider' type='addr-template' required='show'>
-        <td colspan='2'>Address</td>
+        <td colspan='2' name='addressHeader'></td>
         <td>
-            <span>Mailing</span><input type='radio' name='mailing_address'>
-            <span>Billing</span><input type='radio' name='billing_address'>
+            <span name='mailingAddress'></span><input type='radio' name='mailing_address'>
+            <span name='billingAddress'></span><input type='radio' name='billing_address'>
             <button dojoType='dijit.form.Button' scrollOnFocus='false' name='delete-button' class='uedit-addr-del-button'>X</button>
         </td>
     </tr>
 
     <tr name='uedit-addr-pending-row' type='addr-template' class='pending-addr-row hidden'>
         <td colspan='3'>
-            <span style='padding-right:10px;'>This is a pending address: </span>
-            <button dojoType='dijit.form.Button' scrollOnFocus='false'  name='approve-button'>Approve Address</button>
+            <span style='padding-right:10px;' name='addressPending'></span>
+            <button dojoType='dijit.form.Button' scrollOnFocus='false'  name='approve-button'></button>
             <div name='replaced-addr-div'>
                 <div name='replaced-addr'></div>
             </div>
@@ -80,7 +78,7 @@
 
     <tr name='uedit-addr-owner-row' type='addr-template' class='pending-addr-row hidden'>
         <td colspan='3'>
-            <span style='padding-right:10px;'>This address is owned by another user: </span>
+            <span style='padding-right:10px;' name='address-already-owned'></span>
             <a href='javascript:void(0);'  name='addr-owner'></a>
         </td>
     </tr>
 
     <tr id='new-addr-row' class='newaddr-row' required='show'>
         <td colspan='0' style='text-align:center;'>
-            <button dojoType='dijit.form.Button' onClick='uEditNewAddr' scrollOnFocus='false'>New Address</button>
+            <button dojoType='dijit.form.Button' onClick='uEditNewAddr' scrollOnFocus='false' name='addressNew'></button>
         </td>
     </tr>
 
     <!-- stat cats -->
-    <tr class='divider' id='stat-cat-divider' required='suggested'><td colspan='0'>Statistical Categories</td></tr>
+    <tr class='divider' id='stat-cat-divider' required='suggested'><td colspan='0' id='statCats'></td></tr>
     <tr id='stat-cat-row-template' required='suggested'><td class='uedit-help'/><td name='name'/><td name='widget'/></tr>
 
     <!-- surveys -->
index 2cce6c2..2fbe422 100644 (file)
@@ -861,8 +861,15 @@ function add_volumes() {
 
         var title = document.getElementById('offlineStrings').getFormattedString('staff.circ.copy_status.add_volumes.title', [docid]);
 
-        var horizontal_interface = String( g.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
-        var url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+        var url;
+        var unified_interface = String( g.data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
+        if (unified_interface) {
+            var horizontal_interface = String( g.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
+            url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+        } else {
+            url = window.xulG.url_prefix( urls.XUL_VOLUME_COPY_CREATOR_ORIGINAL );
+        }
+
         var w = xulG.new_tab(
             url,
             { 'tab_name' : title },
index 2f56b15..bc8c11d 100644 (file)
@@ -1928,8 +1928,14 @@ commands:
     },
     'volume_item_creator' : function(params) {
         var obj = this;
-        var horizontal_interface = String( obj.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
-        var url = obj.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+        var url;
+        var unified_interface = String( obj.data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
+        if (unified_interface) {
+            var horizontal_interface = String( obj.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
+            url = obj.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+        } else {
+            url = obj.url_prefix( urls.XUL_VOLUME_COPY_CREATOR_ORIGINAL );
+        }
         var w = obj.new_tab(
             url,
             { 'tab_name' : document.getElementById('offlineStrings').getString('staff.cat.create_or_rebarcode_items') },
index aa1608a..4f9cbdd 100644 (file)
@@ -22,6 +22,16 @@ util.print = function (context) {
     }
     this.oils_printer_external_cmd = has_key ? prefs.getCharPref(key) : '';
 
+    try {
+        if (prefs.prefHasUserValue('print.always_print_silent')) {
+            if (! prefs.getBoolPref('print.always_print_silent')) {
+                prefs.clearUserPref('print.always_print_silent');
+            }
+        }
+    } catch(E) {
+        dump('Error in print.js trying to clear print.always_print_silent\n');
+    }
+
     return this;
 };
 
index 82f5de0..8c3e389 100644 (file)
@@ -67,10 +67,13 @@ g.printer_settings = function() {
         print_silent_pref = g.prefs.getBoolPref('print.always_print_silent');
     }
     g.prefs.setBoolPref('print.always_print_silent', false);
+    g.prefs.clearUserPref('print.always_print_silent');
     var w = get_contentWindow(document.getElementById('sample'));
     g.print.NSPrint(w ? w : window, false, {});
     g.print.save_settings();
-    g.prefs.setBoolPref('print.always_print_silent', print_silent_pref);
+    if (print_silent_pref) {
+        g.prefs.setBoolPref('print.always_print_silent', true);
+    }
 }
 
 g.set_print_strategy = function(which) {
index db87e5b..44bc145 100644 (file)
@@ -147,8 +147,14 @@ function add_volumes() {
 
         var title = document.getElementById('offlineStrings').getFormattedString('staff.circ.copy_status.add_volumes.title', [docid]);
 
-        var horizontal_interface = String( g.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
-        var url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+        var url;
+        var unified_interface = String( g.data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
+        if (unified_interface) {
+            var horizontal_interface = String( g.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
+            url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+        } else {
+            url = window.xulG.url_prefix( urls.XUL_VOLUME_COPY_CREATOR_ORIGINAL );
+        }
         var w = xulG.new_tab(
             url,
             { 'tab_name' : title },
index 6aa7241..8c0ddaf 100644 (file)
@@ -299,8 +299,15 @@ cat.copy_browser.prototype = {
 
                                     var title = document.getElementById('catStrings').getString('staff.cat.copy_browser.add_item.title');
 
-                                    var horizontal_interface = String( obj.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
-                                    var url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+                                    var url;
+                                    var unified_interface = String( obj.data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
+                                    if (unified_interface) {
+                                        var horizontal_interface = String( obj.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
+                                        url = xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+                                    } else {
+                                        url = xulG.url_prefix( urls.XUL_VOLUME_COPY_CREATOR_ORIGINAL );
+                                    }
+
                                     var w = xulG.new_tab(
                                         url,
                                         { 'tab_name' : title },
@@ -348,6 +355,12 @@ cat.copy_browser.prototype = {
                             ['command'],
                             function() {
                                 try {
+                                    var unified_interface = String( obj.data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
+                                    if (!unified_interface) {
+                                        obj.controller.control_map['old_cmd_edit_items'][1]();
+                                        return;
+                                    }
+
                                     JSAN.use('util.functional');
 
                                     var list = util.functional.filter_list(
index ad3ce0e..bbecbb5 100644 (file)
@@ -1084,7 +1084,6 @@ g.stash_and_close = function(param) {
             copies = xulG.copies;
         } else {
             copies = g.gather_copies();
-            copies = blob.copies;
         }
 
         var dont_close = false;
index 7997ab5..9a36d7e 100644 (file)
@@ -537,6 +537,7 @@ circ.checkin.prototype = {
                 'barcode' : barcode,
                 'disable_textbox' : function() { 
                     if (!async) {
+                        textbox.blur();
                         textbox.disabled = true; 
                         textbox.setAttribute('disabled', 'true'); 
                     }
@@ -544,9 +545,11 @@ circ.checkin.prototype = {
                 'enable_textbox' : function() { 
                     textbox.disabled = false; 
                     textbox.setAttribute('disabled', 'false'); 
+                    textbox.focus();
                 },
                 'checkin_result' : function(checkin) {
                     textbox.disabled = false;
+                    textbox.focus();
                     //obj.controller.view.cmd_checkin_submit_barcode.setAttribute('disabled', 'false'); 
                     obj.checkin2(checkin,backdate,row_params);
                 },
index e208d5b..522a740 100644 (file)
         label="&staff.checkin.print_receipt.label;" 
         command="cmd_checkin_print"
         accesskey="&staff.checkin.print_receipt.accesskey;"/>
+    <checkbox id="printer_prompt" label="&staff.circ.checkin_overlay.printer_prompt.label;" checked="true" oils_persist="checked"/>
     <checkbox id="trim_list" label="&staff.circ.checkin_overlay.trim_list.label;" checked="true" oils_persist="checked"/> 
     <checkbox id="async_checkin" label="&staff.circ.checkin_overlay.async_checkin.label;" checked="false" oils_persist="checked"/> 
     <checkbox id="strict_barcode" label="&staff.circ.checkin_overlay.strict_barcode.label;" checked="false" oils_persist="checked"/> 
index f94c6a1..bff79af 100644 (file)
@@ -544,8 +544,15 @@ circ.copy_status.prototype = {
     
                                     var title = document.getElementById('circStrings').getFormattedString('staff.circ.copy_status.add_items.title', [r]);
     
-                                    var horizontal_interface = String( obj.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
-                                    var url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+                                    var url;
+                                    var unified_interface = String( obj.data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
+                                    if (unified_interface) {
+                                        var horizontal_interface = String( obj.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
+                                        url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+                                    } else {
+                                        url = window.xulG.url_prefix( urls.XUL_VOLUME_COPY_CREATOR_ORIGINAL );
+                                    }
+
                                     var w = xulG.new_tab(
                                         url,
                                         { 'tab_name' : title },
@@ -696,8 +703,15 @@ circ.copy_status.prototype = {
 
                                     var title = document.getElementById('circStrings').getFormattedString('staff.circ.copy_status.add_volumes.title', [r]);
 
-                                    var horizontal_interface = String( obj.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
-                                    var url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+                                    var url;
+                                    var unified_interface = String( obj.data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
+                                    if (unified_interface) {
+                                        var horizontal_interface = String( obj.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
+                                        url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
+                                    } else {
+                                        url = window.xulG.url_prefix( urls.XUL_VOLUME_COPY_CREATOR_ORIGINAL );
+                                    }
+
                                     var w = xulG.new_tab(
                                         url,
                                         { 'tab_name' : title },
index 3e13c55..35870e4 100644 (file)
@@ -2819,6 +2819,9 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                                     'list' : print_list,
                                     'data' : print_data
                                 };
+                                if ($('printer_prompt')) {
+                                    if (! $('printer_prompt').checked) { params.no_prompt = true; }
+                                }
                                 print.tree_list( params );
                             }
                         } catch(E) {
@@ -3209,6 +3212,9 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                             'list' : print_list,
                             'data' : print_data 
                         };
+                        if ($('printer_prompt')) {
+                            if (! $('printer_prompt').checked) { params.no_prompt = true; }
+                        }
                         print.tree_list( params );
                     }
                 } catch(E) {
index edf589b..085c54a 100644 (file)
@@ -238,6 +238,7 @@ patron.holds.prototype = {
                                     n.setAttribute('toggle','0');
                                     n.setAttribute('label', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.label'));
                                     n.setAttribute('accesskey', document.getElementById("circStrings").getString('staff.circ.holds.alt_view.accesskey'));
+                                    obj.controller.view.save_columns.setAttribute('disabled','false');
                                 } else {
                                     document.getElementById('deck').selectedIndex = 1;
                                     n.setAttribute('toggle','1');
@@ -253,6 +254,7 @@ patron.holds.prototype = {
                                     f.xulG = xulG;
                                     f.xulG.clear_and_retrieve = function() { obj.clear_and_retrieve(); };
                                     f.fetch_and_render_all(true);
+                                    obj.controller.view.save_columns.setAttribute('disabled','true');
                                 }
                             } catch(E) {
                                 alert('Error in holds.js, cmd_alt_view handler: ' + E);
index f2fc92d..b52a9b2 100644 (file)
@@ -3,7 +3,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Evergreen 1.4\n"
 "Report-Msgid-Bugs-To: open-ils-dev@list.georgialibraries.org\n"
-"POT-Creation-Date: 2011-04-18 21:45:31-0400\n"
+"POT-Creation-Date: 2011-04-23 01:33:28-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -11,46 +11,130 @@ msgstr ""
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8-bit\n"
 
+#: register.js:USER_SETTINGS
+msgid "User Settings"
+msgstr ""
+
+#: register.js:DUPE_PATRON_EMAIL
+msgid "Found ${0} patron(s) with the same email address"
+msgstr ""
+
+#: register.js:ADDRESS_BILLING
+msgid "Billing"
+msgstr ""
+
+#: register.js:ADDRESS_OWNED
+msgid "This address is owned by another user: "
+msgstr ""
+
+#: register.js:REPLACED_ADDRESS
+msgid "<div>Replaces address <b>${0}</b><br/> ${1} ${2}<br/> ${3}, ${4} ${5}</div>"
+msgstr ""
+
+#: register.js:SHOW_REQUIRED
+msgid "Show Only Required Fields"
+msgstr ""
+
 #: register.js:DUPE_PATRON_ADDR
 msgid "Found ${0} patron(s) with the same address"
 msgstr ""
 
-#: register.js:INVALID_FORM
-msgid "Form is invalid.  Please edit and try again."
+#: register.js:SAVE
+msgid "Save"
 msgstr ""
 
 #: register.js:DUPE_PATRON_IDENT
 msgid "Found ${0} patron(s) with the same identification"
 msgstr ""
 
-#: register.js:DELETE_ADDRESS
-msgid "Delete address ${0}?"
+#: register.js:ADDRESS_MAILING
+msgid "Mailing"
 msgstr ""
 
-#: register.js:DUPE_PATRON_EMAIL
-msgid "Found ${0} patron(s) with the same email address"
-msgstr ""
-
-#: register.js:DUPE_PATRON_NAME
-msgid "Found ${0} patron(s) with the same name"
+#: register.js:REPLACE_BARCODE
+msgid "Replace Barcode"
 msgstr ""
 
 #: register.js:NEED_ADDRESS
 msgid "An address is required during registration."
 msgstr ""
 
-#: register.js:EXAMPLE
-msgid "Example: "
+#: register.js:PARENT_OR_GUARDIAN
+msgid "Parent/Guardian"
+msgstr ""
+
+#: register.js:ADDRESS_HEADER
+msgid "Address"
 msgstr ""
 
 #: register.js:DUPE_PATRON_PHONE
 msgid "Found ${0} patron(s) with the same phone number"
 msgstr ""
 
-#: register.js:REPLACED_ADDRESS
-msgid "<div>Replaces address <b>${0}</b><br/> ${1} ${2}<br/> ${3}, ${4} ${5}</div>"
+#: register.js:INVALID_FORM
+msgid "Form is invalid.  Please edit and try again."
+msgstr ""
+
+#: register.js:BARCODE_IN_USE
+msgid "Barcode is already in use"
+msgstr ""
+
+#: register.js:EXAMPLE
+msgid "Example: "
+msgstr ""
+
+#: register.js:SHOW_SUGGESTED
+msgid "Show Suggested Fields"
+msgstr ""
+
+#: register.js:ADDRESS_PENDING
+msgid "This is a pending address: "
+msgstr ""
+
+#: register.js:DUPE_USERNAME
+msgid "Username is already in use"
+msgstr ""
+
+#: register.js:DUPE_PATRON_NAME
+msgid "Found ${0} patron(s) with the same name"
 msgstr ""
 
 #: register.js:DEFAULT_ADDRESS_TYPE
 msgid "MAILING"
 msgstr ""
+
+#: register.js:SHOW_ALL
+msgid "Show All Fields"
+msgstr ""
+
+#: register.js:ADDRESS_APPROVE
+msgid "Approve Address"
+msgstr ""
+
+#: register.js:VERIFY_PASSWORD
+msgid "Verify Password"
+msgstr ""
+
+#: register.js:SAVE_CLONE
+msgid "Save &amp; Clone"
+msgstr ""
+
+#: register.js:STAT_CATS
+msgid "Statistical Categories"
+msgstr ""
+
+#: register.js:ADDRESS_NEW
+msgid "New Address"
+msgstr ""
+
+#: register.js:RESET_PASSWORD
+msgid "Reset Password"
+msgstr ""
+
+#: register.js:SEE_ALL
+msgid "See All"
+msgstr ""
+
+#: register.js:DELETE_ADDRESS
+msgid "Delete address ${0}?"
+msgstr ""