LP#1350042 Browser client templates/scripts (phase 1)
authorBill Erickson <berick@esilibrary.com>
Mon, 4 Aug 2014 18:06:02 +0000 (14:06 -0400)
committerBen Shum <bshum@biblio.org>
Fri, 29 Aug 2014 20:12:10 +0000 (16:12 -0400)
 * Templates in Open-ILS/src/templates/staff/
 * JS files in Open-ILS/web/js/ui/default/staff/
 * Also includes a few TPAC modifications for embedded mode
 * Resurrects the pre-XUL user permission editor

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Signed-off-by: Ben Shum <bshum@biblio.org>
200 files changed:
.gitignore
Open-ILS/src/templates/opac/parts/bookbag_actions.tt2
Open-ILS/src/templates/opac/parts/record/copy_table.tt2
Open-ILS/src/templates/staff/README [new file with mode: 0644]
Open-ILS/src/templates/staff/admin/t_user_perms_lookup.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/admin/user_perms.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/admin/workstation/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/admin/workstation/t_print_templates.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/admin/workstation/t_stored_prefs.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/base.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/base_js.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_create.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_delete.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_edit.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_export.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_info.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_selector.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_grid_menu.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_load_shared.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_pending.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_search.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/record/t_view.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/catalog/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/catalog/t_catalog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/catalog/t_holds.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/missing_pieces.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/replace_barcode/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/t_cat_pane.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/t_circ_list_pane.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/t_circs_pane.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/t_holds_pane.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/t_list.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/t_summary_pane.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/t_triggered_events_pane.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/item/t_view.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/share/t_record_summary.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/t_triggered_events_pane.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/checkin/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/checkin/t_checkin.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/checkin/t_checkin_table.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/holds/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/holds/t_pull.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/holds/t_pull_list.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/holds/t_shelf.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/holds/t_shelf_list.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/in_house_use/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/pending.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/register.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_alerts.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_bcsearch.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_bill_history.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_bill_history_payments.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_bill_history_xacts.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_bills.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_credentials.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_edit_due_date_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_edit_perms.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_group.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_holds.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_holds_create.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_holds_list.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_items_out.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_last_patron.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_messages.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_move_to_group_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_new_note_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_notes.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_pending_list.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_renew_with_date_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_search.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_search_results.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_stat_cats.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_triggered_events.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/t_xact_details.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/renew/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/renew/t_renew.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/circ_strings.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/hold_strings.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_backdate_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_bad_barcode_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_bill_patron_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_cancel_hold_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_circ_exists_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_copy_in_transit_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_copy_not_avail_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_event_override_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_hold_copy_quality_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_hold_dates.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_hold_details.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_hold_edit_pickup_lib.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_hold_note_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_hold_notification_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_hold_notification_prefs.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_hold_shelf_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_mark_claims_returned_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_new_message_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_noncat_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_precat_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/share/t_transit_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/config.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/css/circ.css.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/css/print.css.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/css/style.css.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/navbar.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/README [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/index.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_bill_payment.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_bills_current.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_bills_historical.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_checkin.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_checkout.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_hold_pull_list.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_hold_shelf_slip.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_hold_transit_slip.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_holds_for_bib.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_holds_for_patron.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_items_out.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_patron_address.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_patron_note.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_renew.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/print_templates/t_transit_slip.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/t_alert_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/t_autogrid.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/t_confirm_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/t_eframe.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/share/t_prompt_dialog.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/statusbar.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/t_login.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/t_splash.tt2 [new file with mode: 0644]
Open-ILS/web/js/ui/default/opac/staff.js
Open-ILS/web/js/ui/default/staff/Gruntfile.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/README.install [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/admin/user_perms.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/admin/workstation/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/bower.json [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/cat/bucket/record/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/cat/catalog/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/cat/item/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/cat/item/missing_pieces.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/cat/item/replace_barcode/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/cat/services/record.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/checkin/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/holds/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/in_house_use/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/bills.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/checkout.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/holds.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/pending.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/patron/register.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/renew/app.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/services/billing.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/services/circ.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/circ/services/holds.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/package.json [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/auth.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/core.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/coresvc.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/eframe.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/env.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/event.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/file.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/grid.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/hatch.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/idl.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/navbar.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/net.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/org.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/pcrud.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/print.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/startup.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/statusbar.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/strings.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/ui.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/services/user.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/data/eg_mock.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/data/idl2js.pl [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/karma.conf.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/unit/egCore.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/unit/egEvent.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/unit/egHomeApp.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/unit/egIDL.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/unit/egOrg.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/unit/egPatronApp.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/test/unit/egStrings.js [new file with mode: 0644]
Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/xul/staff_client/server/patron/user_edit.xhtml [new file with mode: 0644]
Open-ILS/xul/staff_client/server/patron/user_edit_xhtml.js [new file with mode: 0644]

index 76675d6..073c02d 100644 (file)
@@ -353,3 +353,6 @@ Open-ILS/xul/staff_client/xulrunner-stub.exe
 Thumbs.db
 /js*
 /JavaScript*
+Open-ILS/web/js/ui/default/staff/build/
+Open-ILS/web/js/ui/default/staff/node_modules/
+Open-ILS/web/js/ui/default/staff/bower_components/
index de33841..611d1fc 100644 (file)
@@ -4,7 +4,7 @@
 
     # Wrap a url to open in a new tab in staff client.
     MACRO opac_wrap(url) BLOCK;
-         IF ctx.is_staff;
+         IF ctx.is_staff AND NOT ctx.is_browser_staff;
               # void(0) to return false and not go to new page in current tab.
               "javascript:xulG.new_tab(xulG.urls.XUL_OPAC_WRAPPER, {}, {'opac_url' : 'oils://remote" _ url _ "'});void(0);";
           ELSE;
index 814c4f9..6ecaa10 100644 (file)
@@ -105,6 +105,19 @@ END; # FOREACH bib
             <td headers='copy_header_barcode' property="serialNumber">
                 [% copy_info.barcode | html -%]
                 [% IF ctx.is_staff %]
+                  [%- IF ctx.is_browser_staff %]
+                    <a target="_top" href="[% ctx.base_path %]/staff/cat/item/[% copy_info.id %]">[% l('view') %]</a>
+                    [% IF ctx.has_perm('UPDATE_COPY', copy_info.circ_lib) 
+                        OR ctx.has_perm('UPDATE_COPY', copy_info.call_number_owning_lib) %]
+                        <span> | </span>
+                        <!-- XXX: copy edit is not yet supported in browser client.
+                          Enable this link when available
+                        -->
+                        <!--
+                        <a href="[% ctx.base_path %]/staff/cat/item/[% copy_info.id %]/edit">[% l('edit') %]</a>
+                        -->
+                    [% END %]
+                  [% ELSE %]
                     <a onclick="xulG.new_tab(xulG.urls.XUL_COPY_STATUS, {}, {'from_item_details_new': true, 'barcodes': ['[%- copy_info.barcode | html | replace('\'', '\\\'') -%]']})"
                         href="javascript:;">[% l('view') %]</a>
                     [%# if the user can edit copies, show the copy edit link %]
@@ -116,6 +129,7 @@ END; # FOREACH bib
                             [% l(' edit') %]
                         </a>
                     [% END %]
+                  [% END %]
                 [% END %]
                 [%- IF attrs.gtin13;
                     '<meta property="gtin13" content="' _ attrs.gtin13 _ '" />';
diff --git a/Open-ILS/src/templates/staff/README b/Open-ILS/src/templates/staff/README
new file mode 100644 (file)
index 0000000..9206301
--- /dev/null
@@ -0,0 +1,6 @@
+AnguarJS/Web Staff Client
+=========================
+
+ * TT templates loaded via JS routes must be preceded with t_* (or similar), 
+   otherwise apache will serve the template at that path instead of the 
+   index file since the path maps to a real template.
diff --git a/Open-ILS/src/templates/staff/admin/t_user_perms_lookup.tt2 b/Open-ILS/src/templates/staff/admin/t_user_perms_lookup.tt2
new file mode 100644 (file)
index 0000000..3a23cc5
--- /dev/null
@@ -0,0 +1,24 @@
+<form ng-submit="submitBarcode(args)" role="form" class="form-inline">
+  <div class="input-group">
+
+    <label class="input-group-addon" 
+      for="patron-lookup-barcode" >[% l('Patron Barcode') %]</label>
+
+    <input 
+      focus-me="selectMe" 
+      select-me="selectMe"
+      class="form-control barcode"
+      ng-model="args.barcode" 
+      placeholder="[% l('Patron Barcode') %]"
+      id="patron-lookup-barcode" type="text"/> 
+
+    <input class="btn btn-default" type="submit" value="[% l('Submit') %]"/>
+  </div>
+</form>
+
+<br/>
+<div class="alert alert-warning" ng-show="bcNotFound">
+  [% l('Barcode Not Found: [_1]', '{{bcNotFound}}') %]
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/admin/user_perms.tt2 b/Open-ILS/src/templates/staff/admin/user_perms.tt2
new file mode 100644 (file)
index 0000000..23a1257
--- /dev/null
@@ -0,0 +1,18 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("User Permission Editor"); 
+  ctx.page_app = "egUserPermsEditor";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/eframe.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/admin/user_perms.js"></script>
+[% END %]
+
+<script type="text/ng-template" id="user-perms-template">
+  <eg-embed-frame url="user_perms_url" handlers="funcs"></eg-embed-frame>
+</script>
+
+<div ng-view></div>
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/admin/workstation/index.tt2 b/Open-ILS/src/templates/staff/admin/workstation/index.tt2
new file mode 100644 (file)
index 0000000..3f927a4
--- /dev/null
@@ -0,0 +1,24 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Workstation Administration"); 
+  ctx.page_app = "egWorkstationAdmin";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/user.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/admin/workstation/app.js"></script>
+<script>
+angular.module('egCoreMod').run(['egStrings', function(s) {
+  s.PREFS_REMOVE_KEY_CONFIRM = 
+    '[% l('Delete content for key "[_1]"?', '{{deleteKey}}') %]';
+  s.DEFAULT_WS_LABEL = '[% l('[_1] (Default)', '{{ws}}') %]';
+  s.WS_EXISTS = '[% l("Workstation name already exists.  Use it anyway?") %]';
+}]);
+</script>
+[% END %]
+
+<div ng-view></div>
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2
new file mode 100644 (file)
index 0000000..06067ac
--- /dev/null
@@ -0,0 +1,176 @@
+<div class="container" id="admin-workstation-printing">
+
+  <style>
+    /* TODO: more context and move me */
+    textarea {
+      height: 400px;
+      width: 100%;
+    }
+    .tab-pane .row {
+      padding-top: 20px;
+    }
+    h2 { margin-bottom: 15px }
+      
+  </style>
+
+  <div class="row"> 
+    <div class="col-md-12">
+      <h2>[% l('Printer Settings for Remote Printing') %]</h2>
+    </div>
+  </div>
+
+  <div class="row"> 
+    <div class="col-md-12">
+      <ul class="nav nav-tabs">
+        <li ng-class="{active : context == 'default'}">
+          <a href='' ng-click="setContext('default')">[% l('Default') %]</a>
+        </li>
+        <li ng-class="{active : context == 'receipt'}">
+          <a href='' ng-click="setContext('receipt')">[% l('Receipt') %]</a>
+        </li>
+        <li ng-class="{active : context == 'label'}">
+          <a href='' ng-click="setContext('label')">[% l('Label') %]</a>
+        </li>
+        <li ng-class="{active : context == 'mail'}">
+          <a href='' ng-click="setContext('mail')">[% l('Mail') %]</a>
+        </li>
+        <li ng-class="{active : context == 'offline'}">
+          <a href='' ng-click="setContext('offline')">[% l('Offline') %]</a>
+        </li>
+        <li ng-class="{active : isTestView}" class="pull-right">
+          <a href='' ng-click="isTestView=true">[% l('Test Printing') %]</a>
+        </li>
+      </ul>
+      <div class="tab-content">
+        <div class="tab-pane active">
+
+          <!-- printer config UI -->
+          <div class="row" ng-hide="isTestView">
+            <div class="col-md-6">
+              <div class="input-group">
+                <div class="input-group-btn" dropdown>
+                  <button type="button" class="btn btn-default dropdown-toggle">
+                    [% l('Select Printer') %]
+                    <span class="caret"></span></button>
+                  <ul class="dropdown-menu">
+                    <li ng-repeat="printer in printers">
+                      <a href='' ng-click="setPrinter(printer.name)">
+                        {{printer.name}}
+                      </a>
+                    </li>
+                  </ul>
+                </div><!-- /btn-group -->
+                <input ng-if="!printers[0]" type="text" 
+                  class="form-control" disabled="disabled"
+                  value="[% l('No Printers Found') %]">
+                <input ng-if="printers[0] && !printConfig[context]" type="text" 
+                  class="form-control" disabled="disabled"
+                  value="[% l('No Printer Selected') %]">
+                <input ng-if="printConfig[context].printer" type="text" 
+                  class="form-control" disabled="disabled"
+                  value="{{printConfig[context].printer}}">
+              </div><!-- /input-group -->
+            </div><!-- col -->
+            <div class="col-md-6">
+              <div class="input-group">
+                <div class="input-group-btn">
+                  <button type="button" 
+                    ng-click="configurePrinter()"
+                    ng-class="{disabled : actionPending || !printers[0]}"
+                    class="btn btn-default btn-success">
+                      [% l('Configure Printer') %]
+                  </button>
+                  <button type="button" 
+                    ng-click="resetConfig()"
+                    ng-class="{disabled : actionPending}"
+                    class="btn btn-default btn-warning">
+                      [% l('Reset Configuration') %]
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div><!-- row -->
+          <div class="row" ng-hide="isTestView"> 
+            <div class="col-md-12">
+              <h2>[% l('Compiled Printer Settings') %]</h2>
+              <pre>{{printerConfString()}}</pre>
+            </div><!-- col -->
+          </div><!-- row -->
+
+          <!-- printer test UI -->
+          <div class="row" ng-show="isTestView"> 
+            <div class="col-md-10">
+              <div class="btn-group">
+                <button type="button" 
+                  class="btn btn-default btn-lg" 
+                  ng-class="{active : contentType=='text/plain'}"
+                  ng-click="setContentType('text/plain')">[% l('Plain Text') %]</button>
+                <button type="button" 
+                  class="btn btn-default btn-lg" 
+                  ng-class="{active : contentType=='text/html'}"
+                  ng-click="setContentType('text/html')">[% l('HTML') %]</button>
+              </div>
+            </div>
+            <div class="col-md-2">
+              <div class="input-group pull-right">
+                <div class="input-group-btn">
+                  <button type="button" 
+                    ng-click="testPrint()"
+                    class="btn btn-default btn-success">
+                      [% l('Print') %]</button>
+                  <button type="button" 
+                    ng-click="testPrint(true)"
+                    class="btn btn-default btn-info">
+                      [% l('Print with Dialog') %]</button>
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <div class="row" ng-show="isTestView"> 
+            <div class="col-md-12">
+              <div ng-show="contentType=='text/plain'"
+ng-init="textPrintContent='
+[% l('Test Print') %]
+
+1234567890
+
+12345678901234567890
+
+123456789012345678901234567890
+
+1234567890123456789012345678901234567890
+
+12345678901234567890123456789012345678901234567890
+
+12345678901234567890123456789012345678901234567890123456790
+
+[% l('Test Print') %]
+'">
+        <pre><textarea>{{textPrintContent}}</textarea></pre>
+      </div>
+
+      <div ng-show="contentType=='text/html'">
+        <textarea ng-model="htmlPrintContent" 
+ng-init="htmlPrintContent='
+<div>
+  <style>p { color: blue }</style>
+  <h2>[% l('Test HTML Print') %]</h2>
+  <br/>
+  <img src=\'https://[% ctx.hostname %]/opac/images/main_logo.png\' width=\'140\' height=\'24\'/>
+  <p>[% l('Welcome, Stranger!') %]</p>
+  <p>{{value1}}</p>
+  <p>{{value2}}</p>
+  <p>{{date_value | date}}</p>
+</div>
+'">
+                </textarea>
+              </div><!-- html content -->
+            </div><!-- col -->
+          </div><!-- row -->
+        </div><!-- tab pane -->
+      </div><!-- tab content -->
+    </div><!-- col -->
+  </div><!-- row -->
+</div><!-- container -->
+
diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_print_templates.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_print_templates.tt2
new file mode 100644 (file)
index 0000000..cbc79f8
--- /dev/null
@@ -0,0 +1,59 @@
+<style>
+  /* TODO: move me */
+  .print-template-text {
+    height: 36em;
+    width: 100%;
+  }
+</style>
+
+<h2>[% l('Print Templates') %]</h2>
+
+<div class="row">
+  <div class="col-md-2">[% l('Template Name') %]</div>
+  <div class="col-md-3">
+    <select class="form-control" ng-model="print.template_name" ng-change="template_changed()">
+      <option value="bills_current">[% l('Bills, Current') %]</option>
+      <option value="bills_historical">[% l('Bills, Historical') %]</option>
+      <option value="bill_payment">[% l('Bills, Payment') %]</option>
+      <option value="checkout">[% l('Checkout') %]</option>
+      <option value="hold_transit_slip">[% l('Hold Transit Slip') %]</option>
+      <option value="hold_shelf_slip">[% l('Hold Shelf Slip') %]</option>
+      <option value="holds_for_bibs">[% l('Holds for Bib Record') %]</option>
+      <option value="holds_for_patron">[% l('Holds for Patron') %]</option>
+      <option value="patron_address">[% l('Patron Address') %]</option>
+      <option value="patron_note">[% l('Patron Note') %]</option>
+      <option value="transit_slip">[% l('Transit Slip') %]</option>
+    </select>
+  </div>
+  <div class="col-md-7">
+    <div class="pull-right">
+      <button class="btn btn-default" ng-click="save_locally()">[% l('Save Locally') %]</button>
+    </div>
+  </div>
+  <!-- other stuff -->
+</div>
+
+<hr/>
+
+<div class="row">
+  <div class="col-md-5">
+    <h3>[% l('Preview') %]</h3>
+    <div eg-print-template-output 
+      content="print.template_content" 
+      context="preview_scope"></div>
+  </div>
+  <div class="col-md-7">
+    <h3>[% l('Template') %]</h3>
+    <div ng-if="print.load_failed" class="alert alert-danger">
+      [% l(
+        "Unable to load template '[_1]'.  The web server returned an error.", 
+        '{{print.template_name}}') 
+      %]
+    </div>
+    <div>
+      <textarea ng-model="print.template_content" class="print-template-text">
+      </textarea>
+    </div>
+  </div> <!-- col -->
+</div>
diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2
new file mode 100644 (file)
index 0000000..3a14bbe
--- /dev/null
@@ -0,0 +1,120 @@
+<br/>
+<style>
+  #admin-workstation-container .row {
+    margin-top: 5px;
+  }
+  #admin-workstation-container .new-entry {
+    margin-top: 10px;
+    padding-top: 10px;
+    border-top: 2px solid #F5F5F5;
+  }
+</style>
+
+<div class="container" id="admin-workstation-container">
+
+  <div class="row">
+    <div class="col-md-6">
+      <div class="checkbox">
+        <label>
+          <input type="checkbox" ng-class="{disabled : !userHasAdminPerm}"
+            ng-model="hatchRequired" ng-change="updateHatchRequired()">
+[% l('This workstation uses a remote print / storage service ("Hatch")?') %]
+        </label>
+      </div>
+    </div><!-- row -->
+  </div>
+  <div class="row">
+    <div class="col-md-6">
+      <input type='text' class='form-control'  
+        ng-disabled="!hatchRequired || !userHasRegPerm"
+        title="[% l('Hatch URL') %]"
+        placeholder="[% l('Hatch URL') %]"
+        ng-change='updateHatchURL()' ng-model='hatchURL'/>
+    </div>
+  </div>
+
+  <div class="row new-entry">
+    <div class="col-md-6">
+      [% l('Workstations Registered With This Computer') %]
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-md-6">
+      <select class="form-control" ng-model="selectedWS">
+        <option ng-repeat="ws in workstations" value="{{ws}}"
+          ng-selected="ws == selectedWS">
+          {{getWSLabel(ws)}}
+        </option>
+      </select>
+    </div>
+  </div>
+
+  <div class="row">
+    <div class="col-md-6">
+      <button class="btn btn-default" ng-click="useWS()">
+        [% l('Use Now') %]
+      </button>
+      <button class="btn btn-default" ng-click="setDefaultWS()">
+        [% l('Mark As Default') %]
+      </button>
+      <button class="btn btn-default btn-danger disabled">
+        [% l('Delete') %]
+      </button>
+    </div>
+  </div>
+
+  <div class="row new-entry">
+    <div class="col-md-6">
+      [% l('Register a New Workstation For This Computer') %]
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-md-6">
+      <div class="input-group">
+        <div class="input-group-btn">
+          <eg-org-selector 
+            selected="contextOrg"
+            hidden-test="wsOrgHidden">
+          </eg-org-selector>
+        </div>
+        <input type='text' class='form-control'  
+          title="[% l('Workstation Name') %]"
+          placeholder="[% l('Workstation Name') %]"
+          ng-model='newWSName'/>
+        <div class="input-group-btn">
+          <button class="btn btn-default" ng-click="registerWS()">
+            [% l('Register') %]
+          </button>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <div class="row new-entry">
+    <div class="col-md-6">
+      <span class="glyphicon glyphicon-print"></span>
+      <a target="_self" href="./admin/workstation/print/config">
+        [% l('Printer Settings') %]
+      </a>
+    </div>
+  </div>
+
+  <div class="row new-entry">
+    <div class="col-md-6">
+      <span class="glyphicon glyphicon-film"></span>
+      <a target="_self" href="./admin/workstation/print/templates">
+        [% l('Print Templates') %]
+      </a>
+    </div>
+  </div>
+
+  <div class="row new-entry">
+    <div class="col-md-6">
+      <span class="glyphicon glyphicon-info-sign"></span>
+      <a target="_self" href="./admin/workstation/stored_prefs">
+        [% l('Stored Preferences') %]
+      </a>
+    </div>
+  </div>
+
+</div>
diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_stored_prefs.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_stored_prefs.tt2
new file mode 100644 (file)
index 0000000..dc031b4
--- /dev/null
@@ -0,0 +1,65 @@
+<style>
+  /* TODO */
+  #stored-prefs-container .selected {
+    background-color: #F5F5F5;   
+  }
+  #stored-prefs-container .row {
+    padding-top: 10px;
+  }
+</style>
+<div class="container" id="stored-prefs-container">
+  <div class="row">
+    <div class="col-md-12">
+      <h2>[% l('Stored User Preferences') %]</h2>
+      <div class="well">
+[% |l %]
+Preference values are stored as JSON strings.  
+Click on a preference to view the stored value.
+Click on the delete (X) button to remove a preference's value.
+[% END %]
+      </div>
+    </div>
+  </div>
+
+  <div class="row">
+    <div class="col-md-4">
+
+      <ul class="nav nav-tabs">
+        <li ng-class="{active : context == 'local'}">
+          <a href='' ng-click="setContext('local')">[% l('Local Prefs') %]</a>
+        </li>
+        <li ng-class="{active : context == 'remote'}">
+          <a href='' ng-click="setContext('remote')">[% l('Remote Prefs') %]</a>
+        </li>
+      </ul>
+      <div class="tab-content">
+        <div class="tab-pane active">
+
+          <div class="row" ng-repeat="key in keys[context]">
+            <div class="col-md-1">{{$index + 1}}.</div>
+            <div class="col-md-8 stored-prefs-key" 
+              ng-class="{selected : currentKey == key}">
+              <a href='' ng-click="selectKey(key)">{{key}}</a>
+            </div>
+            <div class="col-md-1">
+              <!-- padding to give the buttom some overflow space -->
+            </div>
+            <div class="col-md-1" class="stored-prefs-remove-button">
+              <button class="btn btn-default btn-danger"
+                ng-class="{disabled : !userHasDeletePerm}"
+                ng-click="removeKey(key)" title="[% l('Remove Item') %]">
+                <span class="glyphicon glyphicon-remove"></span>
+              </button>
+            </div>
+          </div><!-- row -->
+
+        </div><!-- tab pane -->
+      </div><!-- tab content -->
+    </div><!-- col -->
+
+    <div class="col-md-8">
+      <pre>{{getCurrentKeyContent()}}</pre>
+    </div><!-- col -->
+
+  </div><!-- row -->
+</div><!-- container -->
diff --git a/Open-ILS/src/templates/staff/base.tt2 b/Open-ILS/src/templates/staff/base.tt2
new file mode 100644 (file)
index 0000000..ce9cc5e
--- /dev/null
@@ -0,0 +1,48 @@
+<!doctype html>
+[%- PROCESS 'staff/config.tt2' %]
+<html lang="[% ctx.locale %]"
+    [%- IF ctx.page_app %] ng-app="[% ctx.page_app %]"[% END -%]
+    [%- IF ctx.page_ctrl %] ng-controller="[% ctx.page_ctrl %]"[% END %]>
+  <head>
+    <title>[% l('Evergreen Staff [_1]', ctx.page_title) %]</title>
+    <base href="/eg/staff/">
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    [% IF EXPAND_WEB_IMPORTS %]
+    <link rel="stylesheet" href="[% WEB_BUILD_PATH %]/css/bootstrap.min.css" />
+    <link rel="stylesheet" href="[% WEB_BUILD_PATH %]/css/hotkeys.min.css" />
+    [% ELSE %]
+    <link rel="stylesheet" href="[% WEB_BUILD_PATH %]/css/evergreen-staff-client-deps.[% EVERGREEN_VERSION %].min.css" />
+    [% END %]
+    <link rel="stylesheet" href="[% ctx.base_path %]/staff/css/style.css" />
+    <link rel="stylesheet" href="[% ctx.base_path %]/staff/css/print.css" type="text/css" media="print" />
+  </head>
+  <body>
+
+    <!-- load the navbar template inline since it's used on every page -->
+    <script type="text/ng-template" id="eg-navbar-template">
+      [% INCLUDE "staff/navbar.tt2" %]
+    </script>
+
+    <!-- instantiate the navbar by invoking it's name -->
+    <eg-navbar></eg-navbar>
+
+    <!-- main page content goes here -->
+    <div id="top-content-container" class="container">[% content %]</div>
+
+    [% 
+      # status bar along bottom of page
+      INCLUDE "staff/statusbar.tt2";
+
+      # script imports
+      INCLUDE "staff/base_js.tt2";
+
+      # App-specific JS load commands go into an APP_JS block.
+      PROCESS APP_JS;
+    %]
+
+    <!-- content printed via the browser is inserted here for 
+         DOM-ification prior to delivery to the printer -->
+    <div id="print-div" eg-print-container></div>
+  </body>
+</html>
diff --git a/Open-ILS/src/templates/staff/base_js.tt2 b/Open-ILS/src/templates/staff/base_js.tt2
new file mode 100644 (file)
index 0000000..76bc5a3
--- /dev/null
@@ -0,0 +1,47 @@
+<script src="/IDL2js"></script>
+
+[% IF EXPAND_WEB_IMPORTS %]
+
+<!-- angular -->
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/build/js/angular.min.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/build/js/angular-route.min.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/build/js/ui-bootstrap-tpls.min.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/build/js/hotkeys.min.js"></script>
+
+<!-- IDL / opensrf (network) -->
+<script src="[% ctx.media_prefix %]/js/dojo/opensrf/JSON_v1.js"></script>
+<script src="[% ctx.media_prefix %]/js/dojo/opensrf/opensrf.js"></script>
+<script src="[% ctx.media_prefix %]/js/dojo/opensrf/opensrf_ws.js"></script>
+
+<!-- evergreen core services -->
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/core.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/strings.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/idl.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/event.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/net.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/auth.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/pcrud.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/env.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/org.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/startup.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/hatch.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/print.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/coresvc.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/navbar.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/statusbar.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+
+[% ELSE %]
+
+<!-- concatenated, minified version of all of the above -->
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/build/js/evergreen-staff-client.[% EVERGREEN_VERSION %].min.js"></script>
+
+[% END %]
+
+<script>
+  // Configure OpenSRF
+  // pending api_level thunking in C
+  // OpenSRF.api_level = 2;
+  OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_WS;
+</script>
+
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/index.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/index.tt2
new file mode 100644 (file)
index 0000000..2f21e72
--- /dev/null
@@ -0,0 +1,65 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Record Buckets"); 
+  ctx.page_app = "egCatRecordBuckets";
+  ctx.page_ctrl = "RecordBucketCtrl";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/bucket/record/app.js"></script>
+[% END %]
+
+<!-- using native Bootstrap taps because of limitations
+with angular-ui tabsets. it always defaults to making the
+first tab active, so it can't be driven from the route
+https://github.com/angular-ui/bootstrap/issues/910 
+No JS is needed to drive the native tabs, since we're
+changing routes with each tab selection anyway.
+-->
+
+<ul class="nav nav-tabs">
+  <li ng-class="{active : tab == 'search'}">
+    <a href="./cat/bucket/record/search/{{bucketSvc.currentBucket.id()}}">
+        [% l('Record Query') %]
+        <span ng-cloak>({{bucketSvc.queryRecords.length}})</span>
+    </a>
+  </li>
+  <li ng-class="{active : tab == 'pending'}">
+    <a href="./cat/bucket/record/pending/{{bucketSvc.currentBucket.id()}}">
+        [% l('Pending Records') %]
+        <span ng-cloak>({{bucketSvc.pendingList.length}})</span>
+    </a>
+  </li>
+  <li ng-class="{active : tab == 'view'}">
+    <a href="./cat/bucket/record/view/{{bucketSvc.currentBucket.id()}}">
+        [% l('Bucket View') %]
+        <span ng-cloak>({{bucketSvc.currentBucket.items().length}})</span>
+    </a>
+  </li>
+</ul>
+<div class="tab-content">
+  <div class="tab-pane active">
+
+    <!-- bucket info header -->
+    <div class="row">
+      <div class="col-md-6">
+        [% INCLUDE 'staff/cat/bucket/record/t_bucket_info.tt2' %]
+      </div>
+    </div>
+
+    <!-- bucket not accessible warning -->
+    <div class="col-md-10 col-md-offset-1" ng-show="forbidden">
+      <div class="alert alert-warning">
+        [% l('The selected bucket "{{bucketId}}" is not visible to this login.') %]
+      </div>
+    </div>
+
+    <div ng-view></div>
+  </div>
+</div>
+
+[% END %]
+
+
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_create.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_create.tt2
new file mode 100644 (file)
index 0000000..e6bb3fe
--- /dev/null
@@ -0,0 +1,35 @@
+<!-- edit bucket dialog -->
+
+<!-- use <form> so we get submit-on-enter for free -->
+<form class="form-validated" novalidate name="form" ng-submit="ok(args)">
+  <div>
+    <div class="modal-header">
+      <button type="button" class="close" 
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Create Bucket') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group">
+        <label for="edit-bucket-name">[% l('Name') %]</label>
+        <input type="text" class="form-control" focus-me='focusMe' required
+          id="edit-bucket-name" ng-model="args.name" placeholder="[% l('Name...') %]"/>
+      </div>
+      <div class="form-group">
+        <label for="edit-bucket-desc">[% l('Description') %]</label>
+        <input type="text" class="form-control" id="edit-bucket-desc"
+          ng-model="args.desc" placeholder="[% l('Description...') %]"/>
+      </div>
+       <div class="checkbox">
+        <label>
+          <input ng-model="args.pub" type="checkbox"/> 
+          [% l('Publicly Visible?') %]
+        </label>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" ng-disabled="form.$invalid" 
+          class="btn btn-primary" value="[% l('Create Bucket') %]"/>
+      <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+    </div>
+  </div> <!-- modal-content -->
+</form>
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_delete.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_delete.tt2
new file mode 100644 (file)
index 0000000..0ca9887
--- /dev/null
@@ -0,0 +1,16 @@
+<div class="modal-dialog">
+  <div class="modal-content">
+    <div class="modal-header">
+      <button type="button" class="close" 
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Confirm Bucket Delete') %]</h4>
+    </div>
+    <div class="modal-body">
+      <p>[% l('Delete bucket {{bucket().name()}}?') %]</p>
+    </div>
+    <div class="modal-footer">
+      <button class="btn btn-primary" ng-click="ok()">[% l('Delete Bucket') %]</button>
+      <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+    </div>
+  </div> <!-- modal-content -->
+</div> <!-- modal-dialog -->
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_edit.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_edit.tt2
new file mode 100644 (file)
index 0000000..288c577
--- /dev/null
@@ -0,0 +1,34 @@
+<!-- edit bucket dialog -->
+<form class="form-validated" novalidate ng-submit="ok(args)" name="form">
+  <div>
+    <div class="modal-header">
+      <button type="button" class="close" 
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Edit Bucket') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group">
+        <label for="edit-bucket-name">[% l('Name') %]</label>
+        <input type="text" class="form-control" focus-me='focusMe' required
+          id="edit-bucket-name" ng-model="args.name" placeholder="[% l('Name...') %]"/>
+      </div>
+      <div class="form-group">
+        <label for="edit-bucket-desc">[% l('Description') %]</label>
+        <input type="text" class="form-control" id="edit-bucket-desc"
+          ng-model="args.desc" placeholder="[% l('Description...') %]"/>
+      </div>
+       <div class="checkbox">
+        <label>
+          <input ng-model="args.pub" type="checkbox"> 
+          [% l('Publicly Visible?') %]
+        </label>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-primary" 
+          ng-disabled="form.$invalid" value="[% l('Apply Changes') %]"/>
+      <button class="btn btn-warning" ng-click="cancel()"
+          ng-class="{disabled : actionPending}">[% l('Cancel') %]</button>
+    </div>
+  </div> <!-- modal-content -->
+</form>
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_export.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_export.tt2
new file mode 100644 (file)
index 0000000..ffc26d0
--- /dev/null
@@ -0,0 +1,41 @@
+<!-- export bucket dialog -->
+<form ng-submit="ok(args)">
+  <div>
+    <div class="modal-header">
+      <button type="button" class="close" 
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Export Records') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group">
+        <label for="export-bucket-format">[% l('Record Format') %]</label>
+        <select class="form-control" ng-model="args.format" id="export-bucket-format">
+          <option value="XML">[% l('MARC XML') %]</option>
+          <option value="USMARC">[% l('USMARC') %]</option>
+          <option value="UNIMARC">[% l('UNIMARC') %]</option>
+          <option value="BRE">[% l('Evergreen Record Entry') %]</option>
+        </select>
+      </div>
+      <div class="form-group">
+        <label for="export-bucket-encoding">[% l('Encoding') %]</label>
+        <select class="form-control" ng-model="args.encoding" id="export-bucket-encoding">
+          <option value="UTF-8">[% l('UTF-8') %]</option>
+          <option value="MARC8">[% l('MARC8') %]</option>
+        </select>
+      </div>
+
+       <div class="checkbox">
+        <label>
+          <input ng-model="args.holdings" type="checkbox"> 
+          [% l('Include Items?') %]
+        </label>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-primary"
+          ng-click="ok(args)" value="[% l('Export') %]"/>
+      <button class="btn btn-warning" 
+          ng-click="cancel()">[% l('Cancel') %]</button>
+    </div>
+  </div> <!-- modal-content -->
+</form>
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_info.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_info.tt2
new file mode 100644 (file)
index 0000000..877fcf6
--- /dev/null
@@ -0,0 +1,16 @@
+
+<div ng-show="bucket()">
+  <strong>[% l('Bucket: {{bucket().name()}}') %]</strong> 
+  <span>
+    <ng-pluralize count="bucketSvc.currentBucket.items().length"
+      when="{'one': '[% l("1 item") %]', 'other': '[% l("{} items") %]'}">
+    </ng-pluralize>
+  </span> 
+  <span> / [% l('Created {{bucket().create_time() | date}}') %]</span>
+  <span ng-show="bucket().description()"> / {{bucket().description()}}</span>
+</div>
+
+<div ng-show="!bucket()">
+  <strong>[% l('No Bucket Selected') %]</strong>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_selector.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_bucket_selector.tt2
new file mode 100644 (file)
index 0000000..37eef80
--- /dev/null
@@ -0,0 +1,27 @@
+<div class="btn-group text-left" dropdown>
+  <button type="button" class="btn btn-default dropdown-toggle">
+    [% l('Buckets') %]<span class="caret"></span>
+  </button>
+  <ul class="dropdown-menu">
+    <li>
+      <a href='' ng-click="openCreateBucketDialog()">[% l('New Bucket') %]</a>
+    </li>
+    <li ng-class="{disabled : !bucket()}">
+      <a href='' ng-click="openEditBucketDialog()">[% l('Edit Bucket') %]</a>
+    </li>
+    <li ng-class="{disabled : !bucket()}">
+      <a href='' ng-click="openDeleteBucketDialog()">[% l('Delete Bucket') %]</a>
+    </li>
+    <li>
+      <a href='' ng-click="openSharedBucketDialog()">[% l('Load Shared Bucket') %]</a>
+    </li>
+    <li role="presentation" class="divider"></li>
+
+    <!-- list all of this user's buckets -->
+    <li ng-repeat="bkt in bucketSvc.allBuckets" 
+      ng-class="{disabled : bkt.id() == bucket().id()}">
+      <a href='' ng-click="loadBucket(bkt.id())">{{bkt.name()}}</a>
+    </li>
+  </ul>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_grid_menu.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_grid_menu.tt2
new file mode 100644 (file)
index 0000000..a2e2bde
--- /dev/null
@@ -0,0 +1,20 @@
+
+<!-- global grid menu displayed on every Bucket page -->
+<eg-grid-menu-item label="[% l('New Bucket') %]" 
+  handler="openCreateBucketDialog"></eg-grid-menu-item>
+
+<eg-grid-menu-item label="[% l('Edit Bucket') %]" 
+  handler="openEditBucketDialog"></eg-grid-menu-item>
+
+<eg-grid-menu-item label="[% l('Delete Bucket') %]" 
+  handler="openDeleteBucketDialog"></eg-grid-menu-item>
+
+<eg-grid-menu-item label="[% l('Shared Bucket') %]" 
+  handler="openSharedBucketDialog"></eg-grid-menu-item>
+
+<eg-grid-menu-item divider="true"></eg-grid-menu-item>
+
+<eg-grid-menu-item ng-repeat="bkt in bucketSvc.allBuckets" 
+  label="{{bkt.name()}}" handler-data="bkt" 
+  handler="loadBucketFromMenu"></eg-grid-menu-item>
+
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_load_shared.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_load_shared.tt2
new file mode 100644 (file)
index 0000000..9aab308
--- /dev/null
@@ -0,0 +1,25 @@
+<!-- load bucket by id ("shared") -->
+<form class="form-validated" novalidate name="form" ng-submit="ok(args)">
+  <div>
+    <div class="modal-header">
+      <button type="button" class="close" 
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Load Shared Bucket Bucket by ID') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group">
+        <label for="load-bucket-id">[% l('Bucket ID') %]</label>
+        <!-- NOTE: type='number' / required -->
+        <input type="number" class="form-control" focus-me='focusMe' required
+          id="load-bucket-id" ng-model="args.id" placeholder="[% l('Bucket ID...') %]"/>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" ng-disabled="form.$invalid" 
+          class="btn btn-primary" value="[% l('Load Bucket') %]"/>
+      <button class="btn btn-warning" 
+          ng-click="cancel()">[% l('Cancel') %]</button>
+    </div>
+  </div> <!-- modal-content -->
+</form>
+
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_pending.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_pending.tt2
new file mode 100644 (file)
index 0000000..eefc60a
--- /dev/null
@@ -0,0 +1,20 @@
+<eg-grid
+  ng-hide="forbidden"
+  features="-sort,-multisort"
+  id-field="id"
+  idl-class="rmsr"
+  auto-fields="true"
+  items-provider="gridDataProvider"
+  menu-label="[% l('Buckets') %]"
+  persist-key="cat.bucket.record.pending">
+
+  [% INCLUDE 'staff/cat/bucket/record/t_grid_menu.tt2' %]
+
+  <!-- actions drop-down -->
+  <eg-grid-action label="[% l('Add To Bucket') %]" 
+    handler="addToBucket"></eg-grid-action>
+
+  <eg-grid-action label="[% l('Clear List') %]" 
+    handler="clearPendingList"></eg-grid-action>
+
+</eg-grid>
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_search.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_search.tt2
new file mode 100644 (file)
index 0000000..684b139
--- /dev/null
@@ -0,0 +1,46 @@
+<br/>
+
+<!-- search bar -->
+<div class="row">
+  <div class="col-md-6">
+    <form ng-submit="search()">
+      <div class="input-group">
+        <span class="input-group-addon">[% l('Record Query') %]</span>
+        <input type="text" class="form-control" focus-me="focusMe"
+        ng-model="bucketSvc.queryString" placeholder="[% l('Query...') %]">
+      </div>
+    </form>
+  </div>
+</div>
+<br/>
+<div class="row" ng-show="searchInProgress">
+  <div class="col-md-6">
+    <div class="progress progress-striped active">
+        <div class="progress-bar"  role="progressbar" aria-valuenow="100" 
+              aria-valuemin="0" aria-valuemax="100" style="width: 100%">
+            <span class="sr-only">[% l('Searching...') %]</span>
+        </div>
+    </div>
+  </div>
+</div>
+
+
+<eg-grid
+  ng-hide="forbidden"
+  id-field="id"
+  idl-class="rmsr"
+  auto-fields="true"
+  grid-controls="gridControls"
+  menu-label="[% l('Buckets') %]"
+  persist-key="cat.bucket.record.search">
+
+  [% INCLUDE 'staff/cat/bucket/record/t_grid_menu.tt2' %]
+
+  <!-- actions drop-down -->
+  <eg-grid-action label="[% l('Add To Pending') %]"
+    handler="addToPending"></eg-grid-action>
+
+  <eg-grid-action label="[% l('Add To Bucket') %]" 
+    handler="addToBucket"></eg-grid-action>
+
+</eg-grid>
diff --git a/Open-ILS/src/templates/staff/cat/bucket/record/t_view.tt2 b/Open-ILS/src/templates/staff/cat/bucket/record/t_view.tt2
new file mode 100644 (file)
index 0000000..39c866f
--- /dev/null
@@ -0,0 +1,28 @@
+<eg-grid
+  ng-hide="forbidden"
+  id-field="id"
+  idl-class="rmsr"
+  auto-fields="true"
+  grid-controls="gridControls"
+  menu-label="[% l('Buckets') %]"
+  persist-key="cat.bucket.record.view">
+
+  [% INCLUDE 'staff/cat/bucket/record/t_grid_menu.tt2' %]
+
+  <!-- actions drop-down -->
+  <eg-grid-action label="[% l('Remove Selected Records') %]" 
+    handler="detachRecords"></eg-grid-action>
+
+  <eg-grid-action label="[% l('Export Records') %]" 
+    handler="openExportBucketDialog"></eg-grid-action>
+
+  <eg-grid-field path="id" required hidden></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]" path="title">
+    <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.id}}">
+      {{item.title}}
+    </a>
+  </eg-grid-field>
+
+
+</eg-grid>
diff --git a/Open-ILS/src/templates/staff/cat/catalog/index.tt2 b/Open-ILS/src/templates/staff/cat/catalog/index.tt2
new file mode 100644 (file)
index 0000000..9e799d4
--- /dev/null
@@ -0,0 +1,21 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Catalog"); 
+  ctx.page_app = "egCatalogApp";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/eframe.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/services/record.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
+[% INCLUDE 'staff/circ/share/circ_strings.tt2' %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/holds.js"></script>
+[% INCLUDE 'staff/circ/share/hold_strings.tt2' %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/catalog/app.js"></script>
+[% END %]
+
+<div ng-view></div>
+
+[% END %]
+
diff --git a/Open-ILS/src/templates/staff/cat/catalog/t_catalog.tt2 b/Open-ILS/src/templates/staff/cat/catalog/t_catalog.tt2
new file mode 100644 (file)
index 0000000..47f1c6f
--- /dev/null
@@ -0,0 +1,48 @@
+
+<div class="row pad-vert">
+  <div class="col-md-9">
+    <div class="alert alert-info alert-less-pad strong-text-2">
+      <span ng-if="record_tab == 'catalog'">[% l('Catalog') %]</span>
+      <span ng-if="record_tab == 'marc_html'">[% l('MARC HTML') %]</span>
+      <span ng-if="record_tab == 'holds'">[% l('Holds for Record') %]</span>
+    </div>
+  </div>
+  <div class="col-md-3">
+    <!-- actions for this record menu -->
+    <div class="btn-group pull-right" dropdown>
+      <button type="button" 
+          class="btn btn-default dropdown-toggle" ng-disabled="!record_id">
+        [% l('Actions for This Record') %] 
+        <span class="caret"></span>
+      </button>
+      <ul class="dropdown-menu dropdown-menu-right" role="menu">
+        <li><a href dropdown-toggle ng-click="set_record_tab('catalog')">
+            [% l('OPAC View') %]</a></li>
+        <li><a href dropdown-toggle ng-click="set_record_tab('marc_html')">
+            [% l('MARC View') %]</a></li>
+        <li class="divider"></li>
+        <li><a href dropdown-toggle ng-click="set_record_tab('holds')">
+            [% l('View Holds') %]</a></li>
+        <li><a href dropdown-toggle ng-click="mark_hold_transfer_dest()">
+            [% l('Mark as Title Hold Transfer Destination') %]</a></li>
+        <li><a href dropdown-toggle ng-click="transfer_holds_to_marked()">
+            [% l('Transfer All Title Holds') %]</a></li>
+      </ul>
+    </div>
+  </div>
+</div>
+
+<div>
+  <!-- ng-show allows the catalog iframe to stay loaded (unlike ng-if) -->
+  <div ng-show="record_tab == 'catalog'">
+    <eg-embed-frame url="catalog_url" handlers="handlers" onchange="handle_page"></eg-embed-frame>
+  </div>
+  <!-- ng-if the remaining tabs so they can be instantiated on demand -->
+  <div ng-if="record_tab == 'marc_html'">
+    <eg-record-html record-id="record_id"></eg-record-html>
+  </div>
+  <div ng-if="record_tab == 'holds'">
+    [% INCLUDE 'staff/cat/catalog/t_holds.tt2' %]
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/cat/catalog/t_holds.tt2 b/Open-ILS/src/templates/staff/cat/catalog/t_holds.tt2
new file mode 100644 (file)
index 0000000..62af918
--- /dev/null
@@ -0,0 +1,108 @@
+
+<div ng-if="!detail_hold_id">
+  <div class="row">
+    <div class="col-md-3">
+      <div class="input-group">
+        <span class="input-group-addon">[% l('Pickup Library') %]</span>
+        <eg-org-selector selected="pickup_ou" onchange="pickup_ou_changed"></eg-org-selector>
+      </div>
+    </div>
+  </div>
+  <div class="pad-vert"></div>
+
+  <eg-grid
+    id-field="id"
+    features="-sort,-multisort"
+    items-provider="hold_grid_data_provider"
+    grid-controls="hold_grid_controls"
+    persist-key="cat.catalog.holds">
+
+    <eg-grid-menu-item handler="detail_view" 
+      label="[% l('Detail View') %]"></eg-grid-menu-item>
+
+    <eg-grid-action handler="grid_actions.show_recent_circs"
+      label="[% l('Show Last Few Circulations') %]"></eg-grid-action>
+    <eg-grid-action divider="true"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.set_copy_quality"
+      label="[% l('Set Desired Copy Quality') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.edit_pickup_lib"
+      label="[% l('Edit Pickup Library') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.edit_notify_prefs"
+      label="[% l('Edit Notification Settings') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.edit_dates"
+      label="[% l('Edit Hold Dates') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.activate"
+      label="[% l('Activate') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.suspend"
+      label="[% l('Suspend') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.set_top_of_queue"
+      label="[% l('Set Top of Queue') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.clear_top_of_queue"
+      label="[% l('Un-Set Top of Queue') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.transfer_to_marked_title"
+      label="[% l('Transfer To Marked Title') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.mark_damaged"
+      label="[% l('Mark Item Damaged') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.mark_missing"
+      label="[% l('Mark Item Missing') %]"></eg-grid-action>
+    <eg-grid-action divider="true"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.retarget"
+      label="[% l('Find Another Target') %]"></eg-grid-action>
+    <eg-grid-action handler="grid_actions.cancel_hold"
+      label="[% l('Cancel Hold') %]"></eg-grid-action>
+
+    <eg-grid-field label="[% l('Hold ID') %]" path='hold.id'></eg-grid-field>
+    <eg-grid-field label="[% l('Current Copy') %]" 
+      path='hold.current_copy.barcode'>
+      <a href="./cat/item/{{item.hold.current_copy().id()}}/summary" target="_self">
+        {{item.hold.current_copy().barcode()}}
+      </a>
+    </eg-grid-field>
+
+    <eg-grid-field label="[% l('Request Date') %]" path='hold.request_time'></eg-grid-field>
+    <eg-grid-field label="[% l('Capture Date') %]" path='hold.capture_time'></eg-grid-field>
+    <eg-grid-field label="[% l('Available Date') %]" path='hold.shelf_time'></eg-grid-field>
+    <eg-grid-field label="[% l('Hold Type') %]" path='hold.hold_type'></eg-grid-field>
+    <eg-grid-field label="[% l('Pickup Library') %]" path='hold.pickup_lib.shortname'></eg-grid-field>
+
+    <eg-grid-field label="[% l('Title') %]" path='mvr.title'>
+      <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.mvr.doc_id()}}">
+        {{item.mvr.title()}}
+      </a>
+    </eg-grid-field>
+
+    <eg-grid-field label="[% l('Author') %]" path='mvr.author'></eg-grid-field>
+    <eg-grid-field label="[% l('Potential Copies') %]" path='potential_copies'></eg-grid-field>
+    <eg-grid-field label="[% l('Status') %]" path='status_string'></eg-grid-field>
+
+    <eg-grid-field label="[% l('Queue Position') %]" path='queue_position' hidden></eg-grid-field>
+    <eg-grid-field path='hold.*' parent-idl-class="ahr" hidden></eg-grid-field>
+    <eg-grid-field path='copy.*' parent-idl-class="acp" hidden></eg-grid-field>
+    <eg-grid-field path='volume.*' parent-idl-class="acn" hidden></eg-grid-field>
+    <eg-grid-field path='mvr.*' parent-idl-class="mvr" hidden></eg-grid-field>
+  </eg-grid>
+
+  <div class="flex-row pad-vert">
+    <div class="flex-cell"></div>
+    <div>
+      <button class="btn btn-default" ng-click="print_holds()">
+        [% l('Print') %]
+      </button>
+    </div>
+  </div>
+</div>
+
+<!-- hold details -->
+<div ng-if="detail_hold_id">
+  <div class="row">
+    <div class="col-md-2">
+      <button class="btn btn-default" ng-click="list_view()">
+        [% l('List View') %]
+      </button>
+    </div>
+  </div>
+  <div class="pad-vert"></div>
+  <eg-record-summary record='detail_hold_record' 
+    record-id="detail_hold_record_id"></eg-record-summary>
+  <eg-hold-details hold-retrieved="set_hold" hold-id="detail_hold_id"></eg-hold-details>
+</div>
diff --git a/Open-ILS/src/templates/staff/cat/item/index.tt2 b/Open-ILS/src/templates/staff/cat/item/index.tt2
new file mode 100644 (file)
index 0000000..2232a7d
--- /dev/null
@@ -0,0 +1,83 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Item Status"); 
+  ctx.page_app = "egItemStatus";
+  ctx.page_ctrl = "SearchCtrl";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/file.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/eframe.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/item/app.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/services/record.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/billing.js"></script>
+[% END %]
+
+<style>
+  /* FIXME: MOVE ME */
+  #item-status-barcode {width: 16em;}
+  #item-status-form { 
+    margin-bottom: 20px; 
+  }
+</style>
+
+<h1 class="sr-only">[% l('Item Status Display') %]</h1>
+
+<h2>[% l('Scan Item') %]</h2>
+
+<form id="item-status-form" ng-submit="context.search(args)" role="form">
+  <!-- the upload button drops down to the line below when it sits in the
+    same col-md-x as the text input and submit.  avoid by using a flex-row -->
+  <div class="flex-row">
+    <div class="input-group">
+      <input type="text" id="item-status-barcode" class="form-control"
+        select-me="context.selectBarcode" ng-model="args.barcode">
+      <input class="btn btn-default" 
+        type="submit" value="[% l('Submit') %]"/>
+    </div>
+    <!-- give the upload container div some padding to prevent force the
+        upload widget into the vertical middle of the row -->
+    <div class="btn-pad" style="padding:4px;">
+      <div class="flex-row">
+        <div class="strong-text">[% l('OR') %]</div>
+        <div class="btn-pad">
+          <input type="file" eg-file-reader 
+            container="barcodesFromFile" value="[% l('Upload from File') %]">
+        </div>
+      </div>
+    </div>
+    <div class="flex-cell"></div><!-- force the final divs to the right -->
+    <div>
+      <button class="btn btn-default" ng-click="toggleView($event)">
+        <span ng-show="context.page == 'list'">[% l('Detail View') %]</span>
+        <span ng-show="context.page == 'detail'">[% l('List View') %]</span>
+      </button>
+    </div>
+    <!--
+    <div class="btn-group btn-pad" dropdown>
+      <button type="button" class="btn btn-default dropdown-toggle">
+        [% l('Actions for Catalogers') %]<span class="caret"></span>
+      </button>
+      <ul class="dropdown-menu" role="menu">
+      </ul>
+    </div>
+    -->
+  </div><!-- flex row -->
+</form>
+
+
+<div class="row">
+  <div class="col-md-6">
+    <div ng-show="context.itemNotFound" class="alert alert-danger">
+      [% l('Item Not Found') %]
+    </div>
+  </div>
+</div>
+
+<div ng-view></div>
+
+[% END %]
+
+
diff --git a/Open-ILS/src/templates/staff/cat/item/missing_pieces.tt2 b/Open-ILS/src/templates/staff/cat/item/missing_pieces.tt2
new file mode 100644 (file)
index 0000000..2581ba7
--- /dev/null
@@ -0,0 +1,69 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Scan Item as Missing Pieces"); 
+  ctx.page_app = "egItemMissingPieces";
+  ctx.page_ctrl = "MissingPiecesCtrl";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/item/missing_pieces.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
+<script>
+angular.module('egCoreMod').run(['egStrings', function(s) {
+s.CONFIRM_MARK_MISSING_TITLE = "[% l('Mark item as missing pieces?') %]";
+s.CONFIRM_MARK_MISSING_BODY = 
+  "[% l('[_1] / [_2]', '{{barcode}}', '{{title}}') %]";
+s.CIRC_NOT_FOUND = 
+  "[% l('No circulation found for item with barcode [_1].  Item not modified.', '{{barcode}}') %]"
+}])
+</script>
+[% END %]
+
+<div class="container-fluid" style="text-align:center">
+  <div class="alert alert-info alert-less-pad strong-text-2">
+    <span>[% l('Scan Item as Missing Pieces') %]</span>
+  </div>
+</div>
+
+<form ng-submit="submitBarcode(args)" role="form" class="form-inline">
+  <div class="input-group">
+
+    <label class="input-group-addon" 
+      for="patron-lookup-barcode" >[% l('Patron Barcode') %]</label>
+
+    <input 
+      focus-me="selectMe" 
+      select-me="selectMe"
+      class="form-control barcode"
+      ng-model="args.barcode" 
+      placeholder="[% l('Patron Barcode') %]"
+      id="patron-lookup-barcode" type="text"/> 
+
+    <input class="btn btn-default" type="submit" value="[% l('Submit') %]"/>
+  </div>
+</form>
+
+<br/>
+<div class="alert alert-warning" ng-show="bcNotFound">
+  [% l('Barcode Not Found: [_1]', '{{bcNotFound}}') %]
+</div>
+
+<hr/>
+
+<div ng-show="letter"> 
+  <div class="row">
+    <div class="col-md-2">
+      <button ng-click="print_letter()" class="btn btn-default">[% l('Print Letter') %]</button>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-md-6">
+      <textarea ng-model="letter" rows="25" style="width:100%"></textarea>
+    </div>
+  </div>
+</div>
+
+[% END %]
+
+
diff --git a/Open-ILS/src/templates/staff/cat/item/replace_barcode/index.tt2 b/Open-ILS/src/templates/staff/cat/item/replace_barcode/index.tt2
new file mode 100644 (file)
index 0000000..6472a48
--- /dev/null
@@ -0,0 +1,49 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Replace Item Barcode"); 
+  ctx.page_app = "egItemReplaceBarcode";
+  ctx.page_ctrl = "ReplaceItemBarcodeCtrl";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/item/replace_barcode/app.js"></script>
+[% END %]
+
+<h2>[% l('Replace Item Barcode') %]</h2>
+
+<div class="row">
+  <div class="col-md-6 pad-vert">
+    <form role="form" ng-submit="updateBarcode()">
+      <div class="form-group">
+        <label for="barcode1">[% l('Enter Original Barcode for Item') %]</label>
+        <input type="text" class="form-control" id="barcode1" required
+          ng-model="barcode1"
+          placeholder="[% l('Original Barcode...') %]" select-me="focusBarcode">
+      </div>
+      <div class="form-group">
+        <label for="barcode2">[% l('Enter New Barcode for Item') %]</label>
+        <input type="text" class="form-control" id="barcode2" 
+          ng-model="barcode2"
+          required placeholder="[% l('New Barcode...') %]">
+      </div>
+      <button type="submit" class="btn btn-default">[% l('Submit') %]</button>
+    </form>
+  </div>
+</div>
+
+<div class="row pad-vert">
+  <div class="col-md-6">
+    <div class="alert alert-danger" ng-if="copyNotFound">
+      [% l('Copy Not Found') %]
+    </div>
+    <div class="alert alert-success" ng-if="updateOK">
+      <span>[% l('Copy Updated') %]</span>
+      <span class="horiz-pad" ng-if="copyId">
+        <a href="./cat/item/{{copyId}}/summary" target="_self">
+          [% l('View Item Details') %]
+        </a>
+    </div>
+  </div>
+</div>
+[% END %]
diff --git a/Open-ILS/src/templates/staff/cat/item/t_cat_pane.tt2 b/Open-ILS/src/templates/staff/cat/item/t_cat_pane.tt2
new file mode 100644 (file)
index 0000000..43436af
--- /dev/null
@@ -0,0 +1,3 @@
+<h3>[% l('MARC Record') %]</h3>
+
+<eg-record-html record-id="recordId"></eg-record-html>
diff --git a/Open-ILS/src/templates/staff/cat/item/t_circ_list_pane.tt2 b/Open-ILS/src/templates/staff/cat/item/t_circ_list_pane.tt2
new file mode 100644 (file)
index 0000000..9f7bbb5
--- /dev/null
@@ -0,0 +1,51 @@
+<div class="col-md-12" ng-show="!circ_list.length">
+  <div class="alert alert-info">
+    [% l('Item has not circulated.') %]
+  </div>
+</div>
+
+<div class="row" ng-repeat="circ in circ_list">
+  <div class="flex-row">
+    <div class="flex-cell well">
+      <a href="./circ/patron/{{circ.usr().id()}}/checkout" target="_self">
+        [% l('[_1], [_2] [_3] : [_4]', 
+          '{{circ.usr().family_name()}}'
+          '{{circ.usr().first_given_name()}}'
+          '{{circ.usr().second_given_name()}}'
+          '{{circ.usr().card().barcode()}}') %]
+      </a>
+      <span class="pad-horiz">[% l('Circulation ID: [_1]', '{{circ.id()}}') %]</span>
+    </div>
+    <div>
+      <button class="btn btn-default" ng-click="addBilling(circ)">
+        [% l('Add Billing') %]
+      </button>
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Check Out Date') %]</div>
+    <div class="flex-cell well">{{circ.xact_start() | date:'short'}}</div>
+    <div class="flex-cell">[% l('Due Date') %]</div>
+    <div class="flex-cell well">{{circ.due_date() | date:'short'}}</div>
+    <div class="flex-cell">[% l('Stop Fines Time') %]</div>
+    <div class="flex-cell well">{{circ.stop_fines_time() | date:'short'}}</div>
+    <div class="flex-cell">[% l('Checkin Time') %]</div>
+    <div class="flex-cell well">{{circ.checkin_time() | date:'short'}}</div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Check Out Library') %]</div>
+    <div class="flex-cell well">{{circ.circ_lib().shortname()}}</div>
+    <div class="flex-cell">[% l('Renewal?') %]</div>
+    <div class="flex-cell well">{{
+      circ.phone_renewal() == 't' ||
+      circ.desk_renewal() == 't' ||
+      circ.opac_renewal() == 't'
+    }}</div>
+    <div class="flex-cell">[% l('Stop Fines Reason') %]</div>
+    <div class="flex-cell well">{{circ.stop_fines()}}</div>
+    <div class="flex-cell">[% l('Check In Library') %]</div>
+    <div class="flex-cell well">{{circ.checkin_lib().shortname()}}</div>
+  </div>
+  <hr/>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/cat/item/t_circs_pane.tt2 b/Open-ILS/src/templates/staff/cat/item/t_circs_pane.tt2
new file mode 100644 (file)
index 0000000..24a3241
--- /dev/null
@@ -0,0 +1,189 @@
+<div class="col-md-6" ng-show="!prev_circ_summary">
+  <div class="alert alert-info">
+    [% l('No Previous Circ Group') %]
+  </div>
+</div>
+<div class="col-md-6" ng-show="prev_circ_summary">
+  <div class="flex-row">
+    <div class="flex-cell flex-2 strong-text-2">
+      [% l('Previous Circ Group') %]
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Patron') %]</div>
+    <div class="flex-cell well">
+      <a href="./circ/patron/{{prev_circ_usr.id()}}/checkout" 
+        ng-if="prev_circ_summary" target="_self">
+        [% l('[_1], [_2] [_3] : [_4]', 
+          '{{prev_circ_usr.family_name()}}'
+          '{{prev_circ_usr.first_given_name()}}'
+          '{{prev_circ_usr.second_given_name()}}'
+          '{{prev_circ_usr.card().barcode()}}') %]
+      </a>
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Total Circs') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.num_circs()}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkout Date') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.start_time() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkout Workstation') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.checkout_workstation()}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Last Renewed On') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.last_renewal_time() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Renewal Workstation') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.last_renewal_workstation()}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Stop Fines Reason') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.last_stop_fines()}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Stop Fines Time') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.last_stop_fines_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkin Time') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.last_checkin_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkin Scan Time') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.last_checkin_scan_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkin Workstation') %]</div>
+    <div class="flex-cell well">
+      {{prev_circ_summary.last_checkin_workstation()}}
+    </div>
+  </div>
+</div>
+
+<div class="col-md-6" ng-show="!circ">
+  <div class="alert alert-info">
+    [% l('No Recent Circ Group') %]
+  </div>
+</div>
+<div class="col-md-6" ng-show="circ">
+  <div class="flex-row">
+    <div class="flex-cell flex-2 strong-text-2">
+      [% l('Most Recent Circ Group') %]
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Patron') %]</div>
+    <div class="flex-cell well">
+      <a href="./circ/patron/{{circ.usr().id()}}/checkout" 
+        ng-if="circ" target="_self">
+        [% l('[_1], [_2] [_3] : [_4]', 
+          '{{circ.usr().family_name()}}'
+          '{{circ.usr().first_given_name()}}'
+          '{{circ.usr().second_given_name()}}'
+          '{{circ.usr().card().barcode()}}') %]
+      </a>
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Total Circs') %]</div>
+    <div class="flex-cell well">
+      {{circ_summary.num_circs()}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkout Date') %]</div>
+    <div class="flex-cell well">
+      {{circ.xact_start() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkout Workstation') %]</div>
+    <div class="flex-cell well">
+      {{circ.workstation().name()}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Last Renewed On') %]</div>
+    <div class="flex-cell well">
+      {{circ_summary.last_renewal_time() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Renewal Workstation') %]</div>
+    <div class="flex-cell well">
+      {{circ_summary.last_renewal_workstation()}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Stop Fines Reason') %]</div>
+    <div class="flex-cell well">
+      {{circ.stop_fines()}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Stop Fines Time') %]</div>
+    <div class="flex-cell well">
+      {{circ.stop_fines_time() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkin Time') %]</div>
+    <div class="flex-cell well">
+      {{circ.checkin_time() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkin Scan Time') %]</div>
+    <div class="flex-cell well">
+      {{circ.checkin_scan_time() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Checkin Workstation') %]</div>
+    <div class="flex-cell well">
+      {{circ.checkin_workstation.name()}}
+    </div>
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/cat/item/t_holds_pane.tt2 b/Open-ILS/src/templates/staff/cat/item/t_holds_pane.tt2
new file mode 100644 (file)
index 0000000..601c128
--- /dev/null
@@ -0,0 +1,125 @@
+<div class="col-md-6" ng-show="!hold">
+  <div class="alert alert-info">
+    [% l('Item is not captured for a hold') %]
+  </div>
+</div>
+<div class="col-md-6" ng-show="hold">
+  <div class="flex-row">
+    <div class="flex-cell flex-2 strong-text-2">
+      [% l('Captured Hold Info') %]
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Patron') %]</div>
+    <div class="flex-cell well">
+      <a href="./circ/patron/{{hold.usr().id()}}/checkout" 
+        ng-if="hold" target="_self">
+        [% l('[_1], [_2] [_3] : [_4]', 
+          '{{hold.usr().family_name()}}'
+          '{{hold.usr().first_given_name()}}'
+          '{{hold.usr().second_given_name()}}'
+          '{{hold.usr().card().barcode()}}') %]
+      </a>
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Requestor') %]</div>
+    <div class="flex-cell well">
+      <a href="./circ/patron/{{hold.requestor().id()}}/checkout" 
+        ng-if="hold" target="_self">
+        [% l('[_1], [_2] [_3] : [_4]', 
+          '{{hold.requestor().family_name()}}'
+          '{{hold.requestor().first_given_name()}}'
+          '{{hold.requestor().second_given_name()}}'
+          '{{hold.requestor().card().barcode()}}') %]
+      </a>
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Pickup Lib') %]</div>
+    <div class="flex-cell well">
+      {{hold.pickup_lib().shortname()}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Current Shelf Lib') %]</div>
+    <div class="flex-cell well">
+      {{hold.current_shelf_lib().shortname()}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Request Date') %]</div>
+    <div class="flex-cell well">
+      {{hold.request_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Capture Date') %]</div>
+    <div class="flex-cell well">
+      {{hold.capture_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Shelf Time') %]</div>
+    <div class="flex-cell well">
+      {{hold.shelf_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Shelf Expire Time') %]</div>
+    <div class="flex-cell well">
+      {{hold.shelf_expire_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Hold Expire Time') %]</div>
+    <div class="flex-cell well">
+      {{hold.expire_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Behind Desk') %]</div>
+    <div class="flex-cell well">
+      {{hold.behind_desk()}}
+    </div>
+  </div>
+</div>
+
+<div class="col-md-6" ng-show="!transit">
+  <div class="alert alert-info">
+    [% l('Item has not transited') %]
+  </div>
+</div>
+
+<div class="col-md-6" ng-show="transit">
+  <div class="flex-row">
+    <div class="flex-cell flex-2 strong-text-2">
+      [% l('Most Recent Transit') %]
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Transit Source') %]</div>
+    <div class="flex-cell well">
+      {{transit.source().shortname()}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Transit Destination') %]</div>
+    <div class="flex-cell well">
+      {{transit.dest().shortname()}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Transit Send Time') %]</div>
+    <div class="flex-cell well">
+      {{transit.source_send_time() | date:'short'}}
+    </div>
+  </div>
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Transit Receive Time') %]</div>
+    <div class="flex-cell well">
+      {{transit.source_recv_time() | date:'short'}}
+    </div>
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/cat/item/t_list.tt2 b/Open-ILS/src/templates/staff/cat/item/t_list.tt2
new file mode 100644 (file)
index 0000000..cbd2e76
--- /dev/null
@@ -0,0 +1,21 @@
+<eg-grid
+  id-field="index"
+  idl-class="acp"
+  features="-display,-sort,-multisort"
+  main-label="[% l('Item Status') %]"
+  items-provider="gridDataProvider"
+  grid-controls="gridControls"
+  persist-key="cat.items">
+
+  <eg-grid-field label="[% l('Barcode') %]"     path='barcode' visible></eg-grid-field>
+  <eg-grid-field label="[% l('Call Number') %]" path="call_number.label" visible></eg-grid-field>
+  <eg-grid-field label="[% l('Location') %]"    path="location.name" visible></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]"       
+    path="call_number.record.simple_record.title" visible>
+    <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item['call_number.record.id']}}">
+      {{item['call_number.record.simple_record.title']}}
+    </a>
+  </eg-grid-field>
+</eg-grid>
+
diff --git a/Open-ILS/src/templates/staff/cat/item/t_summary_pane.tt2 b/Open-ILS/src/templates/staff/cat/item/t_summary_pane.tt2
new file mode 100644 (file)
index 0000000..6918124
--- /dev/null
@@ -0,0 +1,178 @@
+<style>
+/* FIXME: move me */
+#item-status-alert-msg {
+  flex:7; /* fill the remaining horizontal space */
+}
+</style>
+
+<div class="">
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Barcode') %]</div>
+    <div class="flex-cell well">{{copy.barcode()}}</div>
+
+    <div class="flex-cell">[% l('Circ Library') %]</div>
+    <div class="flex-cell well">{{copy.circ_lib().shortname()}}</div>
+
+    <div class="flex-cell">[% l('Call # Prefix') %]</div>
+    <div class="flex-cell well">
+      {{copy.call_number().prefix().label()}}
+    </div>
+
+    <div class="flex-cell">[% l('Status') %]</div>
+    <div class="flex-cell well">{{copy.status().name()}}</div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Price') %]</div>
+    <div class="flex-cell well">{{copy.price()}}</div>
+
+    <div class="flex-cell">[% l('Owning Library') %]</div>
+    <div class="flex-cell well">{{copy.circ_lib().shortname()}}</div>
+
+    <div class="flex-cell">[% l('Call #') %]</div>
+    <div class="flex-cell well">{{copy.call_number().label()}}</div>
+
+    <div class="flex-cell">[% l('Due Date') %]</div>
+    <div class="flex-cell well">{{circ.due_date() | date:'short'}}</div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('ISBN') %]</div>
+    <div class="flex-cell well">
+      {{copy.call_number().record().simple_record().isbn()}}
+    </div>
+
+    <div class="flex-cell">[% l('Copy Location') %]</div>
+    <div class="flex-cell well">{{copy.location().name()}}</div>
+
+    <div class="flex-cell">[% l('Call # Suffix') %]</div>
+    <div class="flex-cell well">
+      {{copy.call_number().suffix().label()}}
+    </div>
+
+    <div class="flex-cell">[% l('Checkout Date') %]</div>
+    <div class="flex-cell well">{{circ.xact_start() | date:'short'}}</div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Date Created') %]</div>
+    <div class="flex-cell well">{{copy.create_date() | date:'short'}}</div>
+
+    <div class="flex-cell">[% l('Loan Duration') %]</div>
+    <div class="flex-cell well">{{circ.duration()}}</div>
+
+    <div class="flex-cell">[% l('Renewal Type') %]</div>
+    <div class="flex-cell well">
+      <div ng-if="circ.opac_renewal() == 't'">[% l('OPAC') %]</div>
+      <div ng-if="circ.desk_renewal() == 't'">[% l('Desk') %]</div>
+      <div ng-if="circ.phone_renewal() == 't'">[% l('Phone') %]</div>
+    </div>
+
+    <div class="flex-cell">[% l('Checkout Workstation') %]</div>
+    <div class="flex-cell well">{{circ.workstation().name()}}</div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Date Active') %]</div>
+    <div class="flex-cell well">{{copy.active_date() | date:'short'}}</div>
+
+    <div class="flex-cell">[% l('Fine Level') %]</div>
+    <div class="flex-cell well">{{circ.duration_rule().name()}}</div>
+
+    <div class="flex-cell">[% l('Total Circs') %]</div>
+    <div class="flex-cell well">{{total_circs}}</div>
+
+    <div class="flex-cell">[% l('Duration Rule') %]</div>
+    <div class="flex-cell well">{{circ.duration_rule().name()}}</div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Status Changed') %]</div>
+    <div class="flex-cell well">{{copy.status_changed_time() | date:'short'}}</div>
+
+    <div class="flex-cell">[% l('Reference') %]</div>
+    <div class="flex-cell well">{{copy.ref()}}</div>
+
+    <div class="flex-cell">[% l('Total Circs - Current Year') %]</div>
+    <div class="flex-cell well">{{total_circs_this_year}}</div>
+
+    <div class="flex-cell">[% l('Recurring Fine Rule') %]</div>
+    <div class="flex-cell well">{{circ.recurring_fine_rule().name()}}</div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Copy ID') %]</div>
+    <div class="flex-cell well">{{copy.id()}}</div>
+
+    <div class="flex-cell">[% l('OPAC Visible') %]</div>
+    <div class="flex-cell well">{{copy.opac_visible()}}</div>
+
+    <div class="flex-cell">[% l('Total Circs - Prev Year') %]</div>
+    <div class="flex-cell well">{{total_circs_prev_year}}</div>
+
+    <div class="flex-cell">[% l('Max Fine Rule') %]</div>
+    <div class="flex-cell well">{{circ.max_fine_rule().name()}}</div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('TCN') %]</div>
+    <div class="flex-cell well">{{copy.call_number().record().tcn_value()}}</div>
+
+    <div class="flex-cell">[% l('Holdable') %]</div>
+    <div class="flex-cell well">{{copy.opac_visible()}}</div>
+
+    <div class="flex-cell">[% l('Renewal Workstation') %]</div>
+    <div class="flex-cell well">{{circ_summary.last_renewal_workstation()}}</div>
+
+    <div class="flex-cell">[% l('Checkin Time') %]</div>
+    <div class="flex-cell well">
+      {{circ.checkin_time() || 
+        circ_summary.last_checkin_time() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Floating') %]</div>
+    <div class="flex-cell well">{{copy.floating()}}</div>
+
+    <div class="flex-cell">[% l('Circulate') %]</div>
+    <div class="flex-cell well">{{copy.circulate()}}</div>
+
+    <div class="flex-cell">[% l('Remaining Renewals') %]</div>
+    <div class="flex-cell well">{{circ.renewal_remaining()}}</div>
+
+    <div class="flex-cell">[% l('Checkin Scan Time') %]</div>
+    <div class="flex-cell well">
+      {{circ.checkin_scan_time() || 
+        circ_summary.last_checkin_scan_time() | date:'short'}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <!-- empty -->
+    <div class="flex-cell"></div>
+    <div class="flex-cell"></div>
+
+    <div class="flex-cell">[% l('Circ Modifier') %]</div>
+    <div class="flex-cell well">{{copy.circ_modifier().name()}}</div>
+
+    <!-- empty -->
+    <div class="flex-cell"></div>
+    <div class="flex-cell"></div>
+
+    <div class="flex-cell">[% l('Checkin Workstation') %]</div>
+    <div class="flex-cell well">
+      {{circ.checkin_workstation().name() || 
+        circ_summary.last_checkin_workstation().name()}}
+    </div>
+  </div>
+
+  <div class="flex-row">
+    <div class="flex-cell">[% l('Alert Message') %]</div>
+    <div id="item-status-alert-msg" class="well">
+      {{copy.alert_message()}}
+    </div>
+  </div>
+
+</div>
diff --git a/Open-ILS/src/templates/staff/cat/item/t_triggered_events_pane.tt2 b/Open-ILS/src/templates/staff/cat/item/t_triggered_events_pane.tt2
new file mode 100644 (file)
index 0000000..1e32073
--- /dev/null
@@ -0,0 +1,2 @@
+<eg-embed-frame url="triggered_events_url" handlers="funcs"></eg-embed-frame>
+
diff --git a/Open-ILS/src/templates/staff/cat/item/t_view.tt2 b/Open-ILS/src/templates/staff/cat/item/t_view.tt2
new file mode 100644 (file)
index 0000000..82920b4
--- /dev/null
@@ -0,0 +1,34 @@
+<eg-record-summary record="summaryRecord"></eg-record-summary>
+
+<!-- tabbed copy data view -->
+
+<div class="pad-vert"></div>
+
+<ul class="nav nav-tabs">
+  <li ng-class="{active : tab == 'summary'}">
+    <a href="./cat/item/{{copy.id()}}">[% l('Quick Summary') %]</a>
+  </li>
+  <li ng-class="{active : tab == 'circs'}">
+    <a href="./cat/item/{{copy.id()}}/circs">[% l('Recent Circ History') %]</a>
+  </li>
+  <li ng-class="{active : tab == 'circ_list'}">
+    <a href="./cat/item/{{copy.id()}}/circ_list">[% l('Circ History List') %]</a>
+  </li>
+  <li ng-class="{active : tab == 'holds'}">
+    <a href="./cat/item/{{copy.id()}}/holds">[% l('Holds / Transit') %]</a>
+  </li>
+  <li ng-class="{active : tab == 'cat'}">
+    <a href="./cat/item/{{copy.id()}}/cat">[% l('Cataloging Info') %]</a>
+  </li>
+  <li ng-class="{active : tab == 'triggered_events'}">
+    <a href="./cat/item/{{copy.id()}}/triggered_events">[% l('Triggered Events') %]</a>
+  </li>
+</ul>
+<div class="tab-content">
+  <div class="tab-pane active">
+    <div ng-if="tab.length">
+      <div ng-include="'[% ctx.base_path %]/staff/cat/item/t_'+tab+'_pane'"></div>
+    </div>
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/cat/share/t_record_summary.tt2 b/Open-ILS/src/templates/staff/cat/share/t_record_summary.tt2
new file mode 100644 (file)
index 0000000..3de97e5
--- /dev/null
@@ -0,0 +1,53 @@
+<div class="strong-text-2">[% l('Record Summary') %]</div>
+
+<div class="flex-container-striped flex-container-bordered">
+  <div class="flex-row">
+    <div class="flex-cell strong-text">[% l('Title:') %]</div>
+    <div class="flex-cell flex-2">
+      <a target="_self" 
+        href="[% ctx.base_path %]/staff/cat/catalog/record/{{record.id()}}">
+        {{record.simple_record().title()}}
+      </a>
+    </div>
+
+    <div class="flex-cell strong-text">[% l('Edition:') %]</div>
+    <div class="flex-cell"><!-- FIXME: no edition field on simple record --></div>
+
+    <div class="flex-cell strong-text">[% l('TCN:') %]</div>
+    <div class="flex-cell">{{record.tcn_value()}}</div>
+
+    <div class="flex-cell strong-text">[% l('Created By:') %]</div>
+    <div class="flex-cell">{{record.creator().usrname()}}</div>
+  </div><!-- flex-row -->
+
+  <div class="flex-row">
+    <div class="flex-cell strong-text">[% l('Author:') %]</div>
+    <div class="flex-cell flex-2">{{record.simple_record().author()}}</div>
+
+    <div class="flex-cell strong-text">[% l('Pub Date:') %]</div>
+    <div class="flex-cell">
+      {{record.simple_record().pubdate()}}
+    </div>
+
+    <div class="flex-cell strong-text">[% l('Databse ID:') %]</div>
+    <div class="flex-cell">{{record.id()}}</div>
+
+    <div class="flex-cell strong-text">[% l('Last Edited By:') %]</div>
+    <div class="flex-cell">{{record.editor().usrname()}}</div>
+  </div><!-- flex-row -->
+
+  <div class="flex-row">
+    <div class="flex-cell strong-text">[% l('Bib Call #:') %]</div>
+    <div class="flex-cell flex-2"><!-- FIXME: no bib call no on simple rec --></div>
+
+    <div class="flex-cell strong-text"></div>
+    <div class="flex-cell"></div>
+
+    <div class="flex-cell strong-text">[% l('Record Owner:') %]</div>
+    <div class="flex-cell">{{record.owner().shortname()}}</div>
+
+    <div class="flex-cell strong-text">[% l('Last Edited On:') %]</div>
+    <div class="flex-cell">{{record.edit_date() | date:'short'}}</div>
+  </div><!-- flex-row -->
+</div>
+
diff --git a/Open-ILS/src/templates/staff/cat/t_triggered_events_pane.tt2 b/Open-ILS/src/templates/staff/cat/t_triggered_events_pane.tt2
new file mode 100644 (file)
index 0000000..1e32073
--- /dev/null
@@ -0,0 +1,2 @@
+<eg-embed-frame url="triggered_events_url" handlers="funcs"></eg-embed-frame>
+
diff --git a/Open-ILS/src/templates/staff/circ/checkin/index.tt2 b/Open-ILS/src/templates/staff/circ/checkin/index.tt2
new file mode 100644 (file)
index 0000000..dd2c0cf
--- /dev/null
@@ -0,0 +1,19 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Check In"); 
+  ctx.page_app = "egCheckinApp";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/user.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
+[% INCLUDE 'staff/circ/share/circ_strings.tt2' %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/checkin/app.js"></script>
+<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ.css" />
+[% END %]
+
+<div ng-view></div>
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/circ/checkin/t_checkin.tt2 b/Open-ILS/src/templates/staff/circ/checkin/t_checkin.tt2
new file mode 100644 (file)
index 0000000..83b88f5
--- /dev/null
@@ -0,0 +1,225 @@
+<div class="container-fluid" style="text-align:center">
+  <div class="alert alert-info alert-less-pad strong-text-2">
+    <span ng-if="!is_capture">[% l('Checkin Items') %]</span>
+    <span ng-if="is_capture">[% l('Capture Holds') %]</span>
+  </div>
+</div>
+
+<div class="row">
+  <div class="col-md-12">
+    <div class="flex-row left-anchored">
+      <div ng-if="is_backdate()" class="alert-danger pad-all-min">
+        [% l('Backdated Check In [_1]', 
+          '{{checkinArgs.backdate | date:"shortDate"}}') %]
+      </div>
+      <div ng-if="modifiers.no_precat_alert" class="alert-danger pad-all-min">
+        [% l('Ignore Pre-Cataloged Items') %]
+      </div>
+      <div ng-if="modifiers.noop" class="alert-danger pad-all-min">
+        [% l('Suppress Holds and Transits') %]
+      </div>
+      <div ng-if="modifiers.void_overdues" class="alert-danger pad-all-min">
+        [% l('Amnesty Mode') %]
+      </div>
+      <div ng-if="modifiers.auto_print_holds_transits" 
+        class="alert-danger pad-all-min">
+        [% l('Auto-Print Hold and Transit Slips') %]
+      </div>
+      <div ng-if="modifiers.clear_expired" class="alert-danger pad-all-min">
+        [% l('Clear Holds Shelf') %]
+      </div>
+      <div ng-if="modifiers.retarget_holds" class="alert-danger pad-all-min">
+        <div ng-if="modifiers.retarget_holds_all">
+          [% l('Always Retarget Local Holds') %]
+        </div>
+        <div ng-if="!modifiers.retarget_holds_all">
+          [% l('Retarget Local Holds') %]
+        </div>
+      </div>
+      <div ng-if="modifiers.hold_as_transit" class="alert-danger pad-all-min">
+        [% l('Capture Local Holds As Transits') %]
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- checkin form -->
+<div class="row pad-vert">
+  <div class="col-md-4">
+    <form ng-submit="checkin(checkinArgs)" role="form" class="form-inline">
+      <div class="input-group">
+
+        <label class="input-group-addon" 
+          for="patron-checkin-barcode" >[% l('Barcode') %]</label>
+
+        <input focus-me="focusMe" blur-me="blurMe" 
+          class="form-control"
+          ng-model="checkinArgs.copy_barcode" 
+          placeholder="[% l('Barcode') %]"
+          id="patron-checkin-barcode" type="text"/> 
+
+        <input type="submit" class="btn btn-default" value="[% l('Submit') %]"/>
+      </div>
+    </form>
+  </div>
+
+  <div class="col-md-4">
+    <div ng-if="alert" class="col-md-12 alert-danger pad-all-min">
+      <span ng-if="alert.already_checked_in">
+        [% l('[_1] was already checked in.', '{{alert.already_checked_in}}') %]
+      </span>
+      <span ng-if="alert.item_never_circed">
+        [% l('Item [_1] has never circulated.', '{{alert.item_never_circed}}') %]
+      </span>
+    </div>
+  </div>
+
+  <div class="col-md-4" ng-if="!is_capture">
+    <div class="flex-row">
+      <div class="flex-cell"></div>
+      <div class="pad-horiz">[% l('Effective Date') %]</div>
+      <!-- date max= not yet supported -->
+      <div><input eg-date-input
+        class="form-control" ng-model="checkinArgs.backdate"/>
+      </div>
+    </div>
+  </div>
+</div>
+
+<div class="row" ng-if="fine_total">
+  <div class="col-md-12">
+    <span>[% l('Fine Tally:') %]</span>
+    <span class="pad-horiz alert alert-danger">{{fine_total | currency}}</span>
+    <span ng-if="billable_barcode">
+      <span>[% l('Transaction for [_1] billed:', '{{billable_barcode}}') %]</span>
+      <span class="pad-horiz alert alert-danger">{{billable_amount | currency}}</span>
+    </span>
+  </div>
+</div>
+
+<hr/>
+
+[% INCLUDE 'staff/circ/checkin/t_checkin_table.tt2' %]
+
+<div class="row pad-vert">
+  <div class="col-md-10">
+    <div class="flex-row">
+      <div class="flex-cell"></div>
+      <div class="pad-horiz">
+        <button class="btn btn-default" 
+          ng-click="print_receipt()">[% l('Print Receipt') %]</button>
+      </div>
+      <div class="checkbox" ng-if="using_hatch">
+        <label>
+          <input ng-model="show_print_dialog" type="checkbox"/>
+          [% l('Show Print Dialog') %]
+        </label>
+      </div>
+      <div class="pad-horiz" ng-if="using_hatch"></div>
+      <div class="checkbox">
+        <label>
+          <input ng-model="trim_list" type="checkbox"/>
+          [% l('Trim List (20 Rows)') %]
+        </label>
+      </div>
+      <div class="pad-horiz"></div>
+      <div class="checkbox">
+        <label>
+          <input ng-model="strict_barcode" type="checkbox"/>
+          [% l('Strict Barcode') %]
+        </label>
+      </div>
+    </div><!-- flex row -->
+  </div><!-- col -->
+  <div class="col-md-2">
+    <div class="input-group-btn" dropdown>
+      <button type="button" class="btn btn-default dropdown-toggle">
+        [% l('Checkin Modifiers') %]
+        <span class="caret"></span>
+      </button>
+      <ul class="dropdown-menu pull-right">
+        <li>
+          <a href dropdown-toggle 
+            ng-click="toggle_mod('no_precat_alert')">
+            <span ng-if="modifiers.no_precat_alert" 
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.no_precat_alert"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Ignore Pre-cataloged Items') %]</span>
+          </a>
+        </li>
+        <li ng-if="!is_capture"><!-- nonsensical for hold capture -->
+          <a href dropdown-toggle 
+            ng-click="toggle_mod('noop')">
+            <span ng-if="modifiers.noop" 
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.noop"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Suppress Holds and Transits') %]</span>
+          </a>
+        </li>
+        <li>
+          <a href dropdown-toggle 
+            ng-click="toggle_mod('void_overdues')">
+            <span ng-if="modifiers.void_overdues" 
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.void_overdues"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Amnesty Mode') %]</span>
+          </a>
+        </li>
+        <li>
+          <a href dropdown-toggle 
+            ng-click="toggle_mod('auto_print_holds_transits')">
+            <span ng-if="modifiers.auto_print_holds_transits" 
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.auto_print_holds_transits"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Auto-Print Hold and Transit Slips') %]</span>
+          </a>
+        </li>
+        <li>
+          <a href dropdown-toggle 
+            ng-click="toggle_mod('clear_expired')">
+            <span ng-if="modifiers.clear_expired" 
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.clear_expired"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Clear Holds Shelf') %]</span>
+          </a>
+        </li>
+        <li>
+          <a href dropdown-toggle 
+            ng-click="toggle_mod('retarget_holds')">
+            <span ng-if="modifiers.retarget_holds" 
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.retarget_holds"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Retarget Local Holds') %]</span>
+          </a>
+        </li>
+        <li>
+          <a href dropdown-toggle 
+            ng-click="toggle_mod('retarget_holds_all')">
+            <span ng-if="modifiers.retarget_holds_all" 
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.retarget_holds_all"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Retarget All Statuses') %]</span>
+          </a>
+        </li>
+        <li>
+          <a href dropdown-toggle 
+            ng-click="toggle_mod('hold_as_transit')">
+            <span ng-if="modifiers.hold_as_transit" 
+              class="label label-success">&#x2713;</span>
+            <span ng-if="!modifiers.hold_as_transit"
+              class="label label-warning">&#x2717;</span>
+            <span>[% l('Capture Local Holds As Transits') %]</span>
+          </a>
+        </li>
+      </ul>
+    </div><!-- btn grp -->
+  </div><!-- col -->
+</div><!-- row -->
+
diff --git a/Open-ILS/src/templates/staff/circ/checkin/t_checkin_table.tt2 b/Open-ILS/src/templates/staff/circ/checkin/t_checkin_table.tt2
new file mode 100644 (file)
index 0000000..1ee0c09
--- /dev/null
@@ -0,0 +1,89 @@
+<!-- checkins list -->
+
+<eg-grid
+  id-field="index"
+  features="-sort,-multisort"
+  main-label="[% l('Items Checked In') %]"
+  items-provider="gridDataProvider"
+  grid-controls="gridControls"
+  persist-key="{{grid_persist_key}}">
+
+  <eg-grid-action 
+    handler="fetchLastCircPatron"
+    label="[% l('Retrieve Last Patron Who Circulated Item') %]">
+  </eg-grid-action>
+  <eg-grid-action 
+    handler="showBackdateDialog"
+    label="[% l('Backdate Post-Checkin') %]">
+  </eg-grid-action>
+  <eg-grid-action 
+    handler="showMarkDamaged"
+    label="[% l('Mark Items Damaged') %]">
+  </eg-grid-action>
+  <eg-grid-action 
+    handler="abortTransit"
+    label="[% l('Abort Transits') %]">
+  </eg-grid-action>
+
+  <eg-grid-field label="[% l('Alert Msg') %]"   
+    path="acp.alert_message"></eg-grid-field>
+
+  <eg-grid-field label="[% l('Balance Owed') %]"     
+    path='mbts.balance_owed'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Barcode') %]" path="acp_barcode">
+    <!-- FIXME: ng-if / ng-disabled not working since the contents 
+        are $interpolate'd and not $compile'd.
+        I want to hide / disable the href when there is no acp ID 
+    -->
+    <a href="./cat/item/{{item.acp.id()}}/summary" target="_self">
+      {{item.copy_barcode}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Bill #') %]"     
+    path='circ.id'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Checkin Date') %]"    
+    path='circ.checkin_time' dateformat='short'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Family Name') %]"    
+    path='au.family_name'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Finish') %]"    
+    path='circ.stop_fines_time'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Location') %]"    
+    path='acp.location.name'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Route To') %]" path='route_to'>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Start') %]"    
+    path='circ.xact_start'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]" path="title">
+    <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{record.doc_id()}}">
+      {{item.title}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Due Date') %]"    
+    path='circ.due_date' dateformat='short' hidden></eg-grid-field>
+
+  <eg-grid-field label="[% l('Author') %]"      
+    path="author" hidden></eg-grid-field>
+
+  <eg-grid-field label="[% l('Call Number') %]" 
+    path="acn.label" hidden></eg-grid-field>
+
+  <eg-grid-field path="circ.*" parent-idl-class="circ" hidden></eg-grid-field>
+  <eg-grid-field path="acp.*" parent-idl-class="acp" hidden></eg-grid-field>
+  <eg-grid-field path="acn.*" parent-idl-class="acn" hidden></eg-grid-field>
+  <eg-grid-field path="record.*" parent-idl-class="mvr" hidden></eg-grid-field>
+  <eg-grid-field path="mbts.*" parent-idl-class="mbts" hidden></eg-grid-field>
+  <eg-grid-field path="au.*" parent-idl-class="au" hidden></eg-grid-field>
+  <eg-grid-field path="transit.*" parent-idl-class="atc" hidden></eg-grid-field>
+  <eg-grid-field path="hold.*" parent-idl-class="ahr" hidden></eg-grid-field>
+</eg-grid>
+
diff --git a/Open-ILS/src/templates/staff/circ/holds/index.tt2 b/Open-ILS/src/templates/staff/circ/holds/index.tt2
new file mode 100644 (file)
index 0000000..b327738
--- /dev/null
@@ -0,0 +1,30 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Holds Shelf"); 
+  ctx.page_app = "egHoldsApp";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/user.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
+[% INCLUDE 'staff/circ/share/circ_strings.tt2' %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/holds.js"></script>
+[% INCLUDE 'staff/circ/share/hold_strings.tt2' %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/services/record.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/holds/app.js"></script>
+<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ.css" />
+<script>
+angular.module('egCoreMod').run(['egStrings', function(s) {
+  s.CLEAR_SHELF_ACTION_shelf = "[% l('Reshelve') %]";
+  s.CLEAR_SHELF_ACTION_hold = "[% l('Needed for Hold') %]";
+  s.CLEAR_SHELF_ACTION_transit = "[% l('Needs Transiting') %]";
+  s.CLEAR_SHELF_ACTION_pl_changed = "[% l('Wrong Shelf') %]";
+}])
+</script>
+[% END %]
+
+<div ng-view></div>
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/circ/holds/t_pull.tt2 b/Open-ILS/src/templates/staff/circ/holds/t_pull.tt2
new file mode 100644 (file)
index 0000000..de2988b
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="container-fluid" style="text-align:center">
+  <div class="alert alert-info alert-less-pad strong-text-2">
+    <span>[% l('Holds Pull List') %]</span>
+  </div>
+</div>
+
+<div class="pad-vert"></div>
+
+<div ng-if="!detail_hold_id">
+[% INCLUDE 'staff/circ/holds/t_pull_list.tt2' %]
+</div>
+
+<!-- hold details -->
+<div ng-if="detail_hold_id">
+  <div class="row">
+    <div class="col-md-2">
+      <button class="btn btn-default" ng-click="list_view()">
+        [% l('List View') %]
+      </button>
+    </div>
+  </div>
+  <div class="pad-vert"></div>
+  <eg-record-summary record='detail_hold_record' 
+    record-id="detail_hold_record_id"></eg-record-summary>
+  <eg-hold-details hold-retrieved="set_hold" hold-id="detail_hold_id"></eg-hold-details>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/holds/t_pull_list.tt2 b/Open-ILS/src/templates/staff/circ/holds/t_pull_list.tt2
new file mode 100644 (file)
index 0000000..8cea1d1
--- /dev/null
@@ -0,0 +1,88 @@
+<div ng-if="print_list_progress !== null" class="strong-text-2">
+  [% l('Loading... [_1]', '{{print_list_progress}}') %]
+</div>
+
+<eg-grid
+  id-field="id"
+  features="-sort,-multisort"
+  items-provider="gridDataProvider"
+  persist-key="circ.holds.pull">
+
+  <eg-grid-menu-item handler="detail_view" 
+    label="[% l('Detail View') %]"></eg-grid-menu-item>
+
+  <eg-grid-menu-item handler="print_full_list" 
+    label="[% l('Print Full List') %]"></eg-grid-menu-item>
+
+  <!--
+  The Alternate print UI appears to be generated in a very similar
+  fashion to our native full list printer.  Also, since it's 
+  generated from a separate standalone HTML page, the print
+  action bypasses Hatch and goes straight to the browser printer.
+  <eg-grid-menu-item handler="print_list_alt" 
+    label="[% l('Print Full List (Alt)') %]"></eg-grid-menu-item>
+  -->
+
+  <eg-grid-action handler="grid_actions.show_recent_circs"
+    label="[% l('Show Last Few Circulations') %]"></eg-grid-action>
+  <eg-grid-action divider="true"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.set_copy_quality"
+    label="[% l('Set Desired Copy Quality') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_pickup_lib"
+    label="[% l('Edit Pickup Library') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_notify_prefs"
+    label="[% l('Edit Notification Settings') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_dates"
+    label="[% l('Edit Hold Dates') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.activate"
+    label="[% l('Activate') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.suspend"
+    label="[% l('Suspend') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.set_top_of_queue"
+    label="[% l('Set Top of Queue') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.clear_top_of_queue"
+    label="[% l('Un-Set Top of Queue') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.transfer_to_marked_title"
+    label="[% l('Transfer To Marked Title') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.mark_damaged"
+    label="[% l('Mark Item Damaged') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.mark_missing"
+    label="[% l('Mark Item Missing') %]"></eg-grid-action>
+  <eg-grid-action divider="true"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.retarget"
+    label="[% l('Find Another Target') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.cancel_hold"
+    label="[% l('Cancel Hold') %]"></eg-grid-action>
+
+  <eg-grid-field label="[% l('Hold ID') %]" path='hold.id'></eg-grid-field>
+  <eg-grid-field label="[% l('Current Copy') %]" 
+    path='hold.current_copy.barcode'>
+    <a href="./cat/item/{{item.hold.current_copy().id()}}/summary" target="_self">
+      {{item.hold.current_copy().barcode()}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Part') %]" path='part.label'></eg-grid-field>
+  <eg-grid-field label="[% l('Request Date') %]" path='hold.request_time'></eg-grid-field>
+  <eg-grid-field label="[% l('Hold Type') %]" path='hold.hold_type'></eg-grid-field>
+  <eg-grid-field label="[% l('Pickup Library') %]" path='hold.pickup_lib.shortname'></eg-grid-field>
+  <eg-grid-field label="[% l('Copy Location') %]" path='copy.location.name'></eg-grid-field>
+  <eg-grid-field label="[% l('Call Number') %]" path='volume.label'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]" path='mvr.title'>
+    <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.mvr.doc_id()}}">
+      {{item.mvr.title()}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Author') %]" path='mvr.author'></eg-grid-field>
+  <eg-grid-field label="[% l('Potential Copies') %]" path='potential_copies'></eg-grid-field>
+  <eg-grid-field label="[% l('Status') %]" path='status_string' hidden></eg-grid-field>
+
+  <eg-grid-field label="[% l('Queue Position') %]" path='queue_position' hidden></eg-grid-field>
+  <eg-grid-field path='hold.*' parent-idl-class="ahr" hidden></eg-grid-field>
+  <eg-grid-field path='copy.*' parent-idl-class="acp" hidden></eg-grid-field>
+  <eg-grid-field path='volume.*' parent-idl-class="acn" hidden></eg-grid-field>
+  <eg-grid-field path='mvr.*' parent-idl-class="mvr" hidden></eg-grid-field>
+</eg-grid>
+
diff --git a/Open-ILS/src/templates/staff/circ/holds/t_shelf.tt2 b/Open-ILS/src/templates/staff/circ/holds/t_shelf.tt2
new file mode 100644 (file)
index 0000000..b0a4aaf
--- /dev/null
@@ -0,0 +1,40 @@
+<div class="container-fluid" style="text-align:center">
+  <div class="alert alert-info alert-less-pad strong-text-2">
+    <span>[% l('Holds Shelf') %]</span>
+  </div>
+</div>
+
+<div class="row">
+  <div class="col-md-3">
+    <div class="input-group">
+      <span class="input-group-addon">[% l('Pickup Library') %]</span>
+      <eg-org-selector selected="pickup_ou" ng-disabled="is_clearing()"></eg-org-selector>
+    </div>
+  </div>
+  <div class="col-md-3" ng-show="is_clearing()">
+    <progressbar max="clear_progress.max" value="clear_progress.value">
+      <span class="progressbar-text">{{clear_progress.value}} / {{clear_progress.max}}</span>
+    </progressbar>
+  </div>
+</div>
+
+<div class="pad-vert"></div>
+
+<div ng-if="!detail_hold_id">
+[% INCLUDE 'staff/circ/holds/t_shelf_list.tt2' %]
+</div>
+
+<!-- hold details -->
+<div ng-if="detail_hold_id">
+  <div class="row">
+    <div class="col-md-2">
+      <button class="btn btn-default" ng-click="list_view()">
+        [% l('List View') %]
+      </button>
+    </div>
+  </div>
+  <div class="pad-vert"></div>
+  <eg-record-summary record='detail_hold_record' 
+    record-id="detail_hold_record_id"></eg-record-summary>
+  <eg-hold-details hold-retrieved="set_hold" hold-id="detail_hold_id"></eg-hold-details>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/holds/t_shelf_list.tt2 b/Open-ILS/src/templates/staff/circ/holds/t_shelf_list.tt2
new file mode 100644 (file)
index 0000000..3700df9
--- /dev/null
@@ -0,0 +1,85 @@
+
+<eg-grid
+  id-field="id"
+  features="-sort,-multisort"
+  items-provider="gridDataProvider"
+  grid-controls="gridControls"
+  persist-key="circ.holds.shelf">
+
+  <eg-grid-menu-item handler="detail_view" 
+    label="[% l('Detail View') %]"></eg-grid-menu-item>
+
+  <eg-grid-menu-item handler="show_clearable" 
+    hidden="clear_mode" disabled="is_clearing"
+    label="[% l('Show Clearable Holds') %]"></eg-grid-menu-item>
+
+  <eg-grid-menu-item handler="show_active" 
+    hidden="active_mode" disabled="is_clearing"
+    label="[% l('Show All Holds') %]"></eg-grid-menu-item>
+
+  <eg-grid-menu-item handler="clear_holds" disabled="disable_clear"
+    label="[% l('Clear These Holds') %]"></eg-grid-menu-item>
+
+  <eg-grid-action handler="grid_actions.show_recent_circs"
+    label="[% l('Show Last Few Circulations') %]"></eg-grid-action>
+  <eg-grid-action divider="true"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.set_copy_quality"
+    label="[% l('Set Desired Copy Quality') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_pickup_lib"
+    label="[% l('Edit Pickup Library') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_notify_prefs"
+    label="[% l('Edit Notification Settings') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_dates"
+    label="[% l('Edit Hold Dates') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.activate"
+    label="[% l('Activate') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.suspend"
+    label="[% l('Suspend') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.set_top_of_queue"
+    label="[% l('Set Top of Queue') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.clear_top_of_queue"
+    label="[% l('Un-Set Top of Queue') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.transfer_to_marked_title"
+    label="[% l('Transfer To Marked Title') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.mark_damaged"
+    label="[% l('Mark Item Damaged') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.mark_missing"
+    label="[% l('Mark Item Missing') %]"></eg-grid-action>
+  <eg-grid-action divider="true"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.retarget"
+    label="[% l('Find Another Target') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.cancel_hold"
+    label="[% l('Cancel Hold') %]"></eg-grid-action>
+
+  <eg-grid-field label="[% l('Hold ID') %]" path='hold.id'></eg-grid-field>
+  <eg-grid-field label="[% l('Current Copy') %]" 
+    path='hold.current_copy.barcode'>
+    <a href="./cat/item/{{item.hold.current_copy().id()}}/summary" target="_self">
+      {{item.hold.current_copy().barcode()}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Request Date') %]" path='hold.request_time'></eg-grid-field>
+  <eg-grid-field label="[% l('Capture Date') %]" path='hold.capture_time'></eg-grid-field>
+  <eg-grid-field label="[% l('Available Date') %]" path='hold.shelf_time'></eg-grid-field>
+  <eg-grid-field label="[% l('Hold Type') %]" path='hold.hold_type'></eg-grid-field>
+  <eg-grid-field label="[% l('Pickup Library') %]" path='hold.pickup_lib.shortname'></eg-grid-field>
+  <eg-grid-field label="[% l('Post-Clear') %]" path='post_clear'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]" path='mvr.title'>
+    <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.mvr.doc_id()}}">
+      {{item.mvr.title()}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Author') %]" path='mvr.author'></eg-grid-field>
+  <eg-grid-field label="[% l('Potential Copies') %]" path='potential_copies'></eg-grid-field>
+  <eg-grid-field label="[% l('Status') %]" path='status_string'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Queue Position') %]" path='queue_position' hidden></eg-grid-field>
+  <eg-grid-field path='hold.*' parent-idl-class="ahr" hidden></eg-grid-field>
+  <eg-grid-field path='copy.*' parent-idl-class="acp" hidden></eg-grid-field>
+  <eg-grid-field path='volume.*' parent-idl-class="acn" hidden></eg-grid-field>
+  <eg-grid-field path='mvr.*' parent-idl-class="mvr" hidden></eg-grid-field>
+</eg-grid>
+
diff --git a/Open-ILS/src/templates/staff/circ/in_house_use/index.tt2 b/Open-ILS/src/templates/staff/circ/in_house_use/index.tt2
new file mode 100644 (file)
index 0000000..2299603
--- /dev/null
@@ -0,0 +1,81 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("In-House Use"); 
+  ctx.page_app = "egInHouseUseApp";
+  ctx.page_ctrl = "InHouseUseCtrl";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/in_house_use/app.js"></script>
+[% END %]
+
+<style>
+  /* FIXME: MOVE ME */
+  #in-house-use-barcode {width: 16em;}
+  #in-house-use-form { margin-bottom: 20px }
+</style>
+
+<form id="in-house-use-form" ng-submit="checkout(args)" role="form">
+  <div class="row">
+
+    <div class="col-md-2">
+      <div class="input-group">
+        <label class="input-group-addon" for="in-house-num-uses">
+          [% l('# of Uses:') %]
+        </label>
+        <input type="number" min="1" max="{{countMax}}"
+          class="form-control" focus-me="useFocus"
+           id="in-house-num-uses" ng-model="args.num_uses"/>
+      </div>
+    </div>
+
+    <div class="col-md-6">
+      <div class="input-group">
+        <div class="input-group-btn" dropdown>
+          <button type="button" class="btn btn-default dropdown-toggle">
+            {{selectedNcType() || "[% l('Barcode') %]"}}
+            <span class="caret"></span>
+          </button>
+          <ul class="dropdown-menu">
+            <li><a href dropdown-toggle
+              ng-click="args.noncat_type='barcode';bcFocus=true">
+              [% l('Barcode') %]</a>
+            </li>
+            <li class="divider"></li>
+            <li><a href dropdown-toggle
+              ng-repeat='type in nonCatTypes'
+              ng-click="args.noncat_type=type.id()">{{type.name()}}</a>
+            </li>
+          </ul>
+        </div>
+
+        <input type="text" id="in-house-use-barcode" focus-me="bcFocus"
+          class="form-control" ng-model="args.barcode"
+          ng-disabled="args.noncat_type != 'barcode'"/>
+        <input class="btn btn-default" type="submit" value="[% l('Submit') %]"/>
+      </div><!-- input group -->
+    </div><!-- col -->
+  </div><!-- row -->
+</form>
+
+<div clas="row" ng-if="copyNotFound">
+  <div class="col-md-6 alert alert-danger">[% l('Copy Not Found') %]</div>
+</div>
+
+<eg-grid
+  id-field="index"
+  features="-display,-sort,-multisort"
+  main-label="[% l('In-House Use') %]"
+  items-provider="gridDataProvider"
+  persist-key="circ.in_house_use">
+  <eg-grid-field label="[% l('# of Uses') %]"   path='num_uses' visible></eg-grid-field>
+  <eg-grid-field label="[% l('Barcode') %]"     path='copy.barcode' visible></eg-grid-field>
+  <eg-grid-field label="[% l('Call Number') %]" path="copy.call_number.label" visible></eg-grid-field>
+  <eg-grid-field label="[% l('Location') %]"    path="copy.location.name" visible></eg-grid-field>
+  <eg-grid-field label="[% l('Title') %]"       path="title" visible></eg-grid-field>
+</eg-grid>
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/circ/patron/index.tt2 b/Open-ILS/src/templates/staff/circ/patron/index.tt2
new file mode 100644 (file)
index 0000000..9048faa
--- /dev/null
@@ -0,0 +1,175 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Patron"); 
+  ctx.page_app = "egPatronApp";
+  ctx.page_ctrl = "PatronCtrl";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/user.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/eframe.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/billing.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
+[% INCLUDE 'staff/circ/share/circ_strings.tt2' %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/holds.js"></script>
+[% INCLUDE 'staff/circ/share/hold_strings.tt2' %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/cat/services/record.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/app.js"></script>
+
+<!-- load the rest on demand? -->
+
+<!-- required for credentials verify API -->
+<script src="[% ctx.media_prefix %]/js/dojo/opensrf/md5.js"></script>
+
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/checkout.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/items_out.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/holds.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/bills.js"></script>
+
+<!-- TODO: APP_JS should really be called APP_ADDONS or some such.
+    It just means "load these things, too, and load them last" -->
+<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ.css" />
+
+<script>
+angular.module('egCoreMod').run(['egStrings', function(s) {
+  s.ANNOTATE_PAYMENT_MSG = "[% l('Please annotate this payment') %]";
+  s.CONFIRM_REFUND_PAYMENT = 
+    "[% |l('{{xactIds}}') -%]Are you sure you would like to refund excess payment on bills [_1]?  This action will simply put the amount in the Payment Pending column as a negative value.  You must still select Apply Payment!  Certain types of payments may not be refunded.  The refund may be applied to checked transactions that follow the refunded transaction.[% END %]";
+  s.EDIT_BILL_PAY_NOTE = "[% l('Enter new note for #[_1]:','{{ids}}') %]";
+  s.GROUP_ADD_USER = "[% l('Enter the patron barcode') %]";
+  s.RENEW_ITEMS = "[% l('Renew Items?') %]";
+  s.RENEW_ALL_ITEMS = "[% l('Renew All Items?') %]";
+  s.CHECK_IN_CONFIRM = "[% l('Check In Items?') %]";
+}]);
+</script>
+
+[% END %]
+
+<div class="row">
+  <div class="col-md-3">
+    <div ng-show="patron()">
+      <h4 title="{{patron().id()}}">
+        <div class="flex-row">
+          <div class="flex-cell">
+            [% l('[_1], [_2] [_3]', 
+                '{{patron().family_name()}}',
+                '{{patron().first_given_name()}}',
+                '{{patron().second_given_name()}}') %]
+          </div>
+          <div ng-show="tab != 'search'">
+            <a href ng-click="toggle_expand_summary()"
+              title="[% l('Collapse Patron Summary Display') %]"
+              ng-hide="collapse_summary()">
+              <span class="glyphicon glyphicon-resize-small"></span>
+            </a>
+            <a href ng-click="toggle_expand_summary()"
+              title="[% l('Expand Patron Summary Display') %]"
+              ng-show="collapse_summary()">
+              <span class="glyphicon glyphicon-resize-full"></span>
+            </a>
+          </div>
+        </div><!-- row -->
+      </h4>
+    </div><!-- if patron -->
+  </div><!-- col -->
+  <div class="col-md-9">
+    <ul class="nav nav-pills nav-pills-like-tabs">
+      <li ng-class="{active : tab == 'checkout', disabled : !patron()}">
+        <a href="./circ/patron/{{patron().id()}}/checkout">[% l('Check Out') %]</a>
+      </li>
+      <li ng-class="{active : tab == 'items_out', disabled : !patron()}">
+        <a href="./circ/patron/{{patron().id()}}/items_out">
+          [% l('Items Out') %] 
+          <span ng-if="patron()"><!-- lack of space / newline below intentional -->
+          (<span ng-class="{'patron-summary-alert-small' : patron_stats().checkouts.overdue}">{{patron_stats().checkouts.total_out}}</span>)
+          </span>
+        </a>
+      </li>
+      <li ng-class="{active : tab == 'holds', disabled : !patron()}">
+        <a href="./circ/patron/{{patron().id()}}/holds">
+          [% l('Holds') %]
+          <span ng-if="patron()">
+            (<span>{{patron_stats().holds.total}} / {{patron_stats().holds.ready}}</span>)
+          </span>
+        </a>
+      </li>
+      <li ng-class="{active : tab == 'bills', disabled : !patron()}">
+        <a href="./circ/patron/{{patron().id()}}/bills">
+          [% l('Bills') %]
+          <span ng-if="patron()">
+            (<span ng-class="{'patron-summary-alert-small' : patron_stats().fines.balance_owed}">{{patron_stats().fines.balance_owed | currency}}</span>)
+          </span>
+        </a>
+      </li>
+      <li ng-class="{active : tab == 'messages', disabled : !patron()}">
+        <a href="./circ/patron/{{patron().id()}}/messages">[% l('Messages') %]</a>
+      </li>
+      <li ng-class="{active : tab == 'edit', disabled : !patron()}">
+        <a href="./circ/patron/{{patron().id()}}/edit">[% l('Edit') %]</a>
+      </li>
+      <li class="dropdown" ng-class="{active : tab == 'other', disabled : !patron()}">
+        <a href class="dropdown-toggle" data-toggle="dropdown">
+            [% l('Other') %]
+            <b class="caret"></b>
+        </a>
+        <ul class="dropdown-menu">
+          <li>
+            <a href="./circ/patron/{{patron().id()}}/alerts">
+              [% l('Display Alert and Messages') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/{{patron().id()}}/notes">
+              [% l('Notes') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/{{patron().id()}}/triggered_events">
+              [% l('Triggered Events / Notifications') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/{{patron().id()}}/stat_cats">
+              [% l('Statistical Categories') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/{{patron().id()}}/group">
+              [% l('Group Member Details') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/{{patron().id()}}/edit_perms">
+              [% l('User Permission Editor') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/{{patron().id()}}/credentials">
+              [% l('Test Password') %]
+            </a>
+          </li>
+       </ul>
+      </li>
+      <li ng-class="{active : tab == 'search'}" class="pull-right">
+        <a href="./circ/patron/search">[% l('Patron Search') %]</a>
+      </li>
+    </ul>
+  </div><!-- col -->
+</div><!-- row -->
+
+<div class="row">
+  <div class="col-md-3" ng-hide="collapse_summary()">
+    [% INCLUDE 'staff/circ/patron/t_summary.tt2' %]
+  </div>
+  <div ng-class="{'col-md-12' : collapse_summary(),'col-md-9' : !collapse_summary()}">
+    <div class="tab-content">
+      <div class="tab-pane active">
+        <div ng-view></div>
+      </div>
+    </div>
+  </div><!-- col -->
+</div><!-- row -->
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/circ/patron/pending.tt2 b/Open-ILS/src/templates/staff/circ/patron/pending.tt2
new file mode 100644 (file)
index 0000000..21c21cb
--- /dev/null
@@ -0,0 +1,17 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Pending Patrons"); 
+  ctx.page_app = "egPendingPatronsApp";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/user.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/pending.js"></script>
+<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ.css" />
+[% END %]
+
+<div ng-view></div>
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/circ/patron/register.tt2 b/Open-ILS/src/templates/staff/circ/patron/register.tt2
new file mode 100644 (file)
index 0000000..4a3c9ce
--- /dev/null
@@ -0,0 +1,15 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Patron Registration"); 
+  ctx.page_app = "egPatronRegApp";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/eframe.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/register.js"></script>
+<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ.css" />
+[% END %]
+
+<div ng-view></div>
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_alerts.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_alerts.tt2
new file mode 100644 (file)
index 0000000..822240c
--- /dev/null
@@ -0,0 +1,75 @@
+<div>
+
+  <!-- FIXME: move image file -->
+  <img src='/xul/server/skin/media/images/stop_sign.png'>
+
+  <div class="alert alert-info" ng-if="patron_stats().holds.ready > 0">
+    [% l('Holds available: [_1]', '{{patron_stats().holds.ready}}') %]
+  </div>
+
+  <div class="alert alert-warning" ng-if="patronExpired">
+    [% l('Patron account is EXPIRED.') %]
+  </div>
+
+  <div class="alert alert-warning" ng-if="patronExpiresSoon">
+    [% l('Patron account will expire soon.  Please renew.') %]
+  </div>
+
+  <div class="alert alert-warning" ng-if="patron().barred() == 't'">
+    [% l('Patron account is BARRED') %]
+  </div>
+
+  <div class="alert alert-warning" ng-if="patron().active() == 'f'">
+    [% l('Patron account is INACTIVE') %]
+  </div>
+
+  <div class="alert alert-warning" ng-if="retrievedWithInactive">
+    [% l('Patron account retrieved with an INACTIVE card.') %]
+  </div>
+
+  <!-- alert message -->
+  <div class="row" ng-if="patron().alert_message()">
+    <div class="col-md-12">
+      <div class="panel panel-warning">
+        <div class="panel-heading">
+          <div class="panel-title text-center">[% l('Alert Message') %]</div>
+        </div>
+        <div class="panel-body">
+          {{patron().alert_message()}}
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <!-- penalties -->
+  <div class="row" ng-if="alert_penalties().length">
+    <div class="col-md-12">
+      <div class="panel panel-warning">
+        <div class="panel-heading">
+          <div class="panel-title text-center">[% l('Penalties') %]</div>
+        </div>
+        <div class="panel-body">
+          <div class="row" 
+            ng-repeat="penalty in alert_penalties()">
+            <div class="col-md-2">
+              {{penalty.org_unit().shortname()}}
+            </div>
+            <div class="col-md-8"
+              title="{{penalty.standing_penalty().name()}}">
+              {{penalty.standing_penalty().label()}}
+              <div>{{penalty.note()}}</div><!-- force newline -->
+            </div>
+            <div class="col-md-2">
+              {{penalty.set_date() | date:'shortDate'}}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <br/>
+  <div class="well">
+[% l('Press a navigation button above (for example, Check Out) to clear this alert.') %]
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_bcsearch.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_bcsearch.tt2
new file mode 100644 (file)
index 0000000..216b186
--- /dev/null
@@ -0,0 +1,22 @@
+
+<form ng-submit="submitBarcode(args)" role="form" class="form-inline">
+  <div class="input-group">
+
+    <label class="input-group-addon" 
+      for="patron-checkout-barcode" >[% l('Patron Barcode') %]</label>
+
+    <input select-me="selectMe" class="form-control"
+      ng-model="args.barcode" 
+      placeholder="[% l('Patron Barcode') %]"
+      id="patron-checkout-barcode" type="text"/> 
+
+    <input class="btn btn-default" type="submit" value="[% l('Submit') %]"/>
+  </div>
+</form>
+
+<br/>
+<div class="alert alert-warning" ng-show="bcNotFound">
+  [% l('Barcode Not Found: [_1]', '{{bcNotFound}}') %]
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_bill_history.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_bill_history.tt2
new file mode 100644 (file)
index 0000000..6739d7e
--- /dev/null
@@ -0,0 +1,34 @@
+<h2>[% l('Bill History') %]</h2>
+
+<ul class="nav nav-tabs">
+  <li ng-class="{active : bill_tab == 'transactions'}">
+    <a href="./circ/patron/{{patron().id()}}/bill_history/transactions">
+        [% l('Transactions') %]
+    </a>
+  </li>
+  <li ng-class="{active : bill_tab == 'payments'}">
+    <a href="./circ/patron/{{patron().id()}}/bill_history/payments">
+        [% l('Payments') %]
+    </a>
+  </li>
+</ul>
+<div class="tab-content">
+  <div class="tab-pane active">
+
+    <div class="flex-row padded">
+      <div ng-if="bill_tab == 'transactions'">[% l('Selected Billed:') %]</div>
+      <div ng-if="bill_tab == 'transactions'">{{totals.selected_billed() | currency}}</div>
+      <div>[% l('Selected Paid:') %]</div>
+      <div>{{totals.selected_paid() | currency}}</div>
+      <div class="flex-cell"></div>
+      <div>[% l('Start Date:') %]</div>
+      <div><input eg-date-input class="form-control" ng-model="dates.xact_start"/></div>
+      <div>[% l('End Date:') %]</div>
+      <div><input eg-date-input class="form-control" ng-model="dates.xact_finish"/></div>
+    </div><!-- top row -->
+    <hr/>
+    [% INCLUDE 'staff/circ/patron/t_bill_history_xacts.tt2' %]
+    [% INCLUDE 'staff/circ/patron/t_bill_history_payments.tt2' %]
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_bill_history_payments.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_bill_history_payments.tt2
new file mode 100644 (file)
index 0000000..c4fa9d3
--- /dev/null
@@ -0,0 +1,79 @@
+
+<div ng-if="bill_tab == 'payments'" ng-controller="BillPaymentHistoryCtrl">
+
+  <eg-grid
+    idl-class="mp"
+    id-field="id"
+    grid-controls="gridControls">
+
+    <eg-grid-action 
+      label="[% l('Full Details') %]" handler="showFullDetails"></eg-grid-action>
+
+    <eg-grid-field path="amount" label="[% l('Amount') %]"></eg-grid-field>
+    <eg-grid-field path="id" label="[% l('Payment ID') %]"></eg-grid-field>
+    <eg-grid-field path="payment_ts" label="[% l('Payment Time') %]"></eg-grid-field>
+    <eg-grid-field path="note" label="[% l('Note') %]"></eg-grid-field>
+    <eg-grid-field path="voided" label="[% l('Voided') %]"></eg-grid-field>
+    <eg-grid-field path="xact.summary.xact_type" label="[% l('Transaction Type') %]"></eg-grid-field>
+    <eg-grid-field path="xact.summary.last_billing_type" label="[% l('Last Billing Type') %]"></eg-grid-field>
+
+    <eg-grid-field label="[% l('Title') %]" name="title" 
+      path="xact.circulation.target_copy.call_number.record.simple_record.title">
+      <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.record_id}}">{{item.title}}</a>
+    </eg-grid-field>
+
+    <!-- needed for bib link -->
+    <eg-grid-field name="record_id" 
+      path="xact.circulation.target_copy.call_number.record.id" 
+      required hidden></eg-grid-field>
+
+    <eg-grid-field label="[% l('Barcode') %]" name="copy_barcode" 
+      path="xact.circulation.target_copy.barcode">
+      <a target="_self" href="./cat/item/{{item.copy_id}}">{{item.copy_barcode}}</a>
+    </eg-grid-field>
+
+    <!-- needed for item link -->
+    <eg-grid-field name="copy_id" 
+      path="xact.circulation.target_copy.id" required hidden></eg-grid-field>
+
+    <!-- ... -->
+
+    <eg-grid-field path="xact.id" required hidden></eg-grid-field>
+    <eg-grid-field path="xact.usr" required hidden></eg-grid-field>
+    <eg-grid-field path="xact.*" hidden></eg-grid-field>
+    <eg-grid-field path="xact.summary.*" hidden></eg-grid-field>
+
+    <!--
+    <eg-grid-field path="xact.summary.balance_owed"></eg-grid-field>
+    <eg-grid-field path="xact.xact_finish" label="[% l('Finish') %]"></eg-grid-field>
+    <eg-grid-field path="xact.xact_start" label="[% l('Start') %]"></eg-grid-field>
+    <eg-grid-field path="xact.summary.total_owed" label="[% l('Total Billed') %]"></eg-grid-field>
+    <eg-grid-field path="xact.summary.total_paid" label="[% l('Total Paid') %]"></eg-grid-field>
+    <eg-grid-field path="xact.summary.xact_type" label="[% l('Type') %]"></eg-grid-field>
+
+    <eg-grid-field label="[% l('Title') %]" name="title" 
+      path="circulation.target_copy.call_number.record.simple_record.title">
+      <a href="[% ctx.base_path %]/opac/record/{{item.record_id}}">{{item.title}}</a>
+    </eg-grid-field>
+
+    <eg-grid-field name="record_id" 
+      path="circulation.target_copy.call_number.record.id" 
+      required hidden></eg-grid-field>
+
+    <eg-grid-field label="[% l('Barcode') %]" name="copy_barcode" 
+      path="circulation.target_copy.barcode">
+      <a target="_self" href="./cat/item/{{item.copy_id}}">{{item.copy_barcode}}</a>
+    </eg-grid-field>
+
+    <eg-grid-field name="copy_id" 
+      path="circulation.target_copy.id" required hidden></eg-grid-field>
+
+    <eg-grid-field path="summary.last_payment_ts" required hidden></eg-grid-field>
+
+    <eg-grid-field path="summary.*" hidden></eg-grid-field>
+    <eg-grid-field path="circulation.target_copy.*" hidden></eg-grid-field>
+    <eg-grid-field path="circulation.target_copy.call_number.*" hidden></eg-grid-field>
+    -->
+  </eg-grid>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_bill_history_xacts.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_bill_history_xacts.tt2
new file mode 100644 (file)
index 0000000..70f48b6
--- /dev/null
@@ -0,0 +1,49 @@
+
+<div ng-if="bill_tab == 'transactions'" ng-controller="BillXactHistoryCtrl">
+
+  <eg-grid
+    idl-class="mbt"
+    id-field="id"
+    grid-controls="gridControls">
+
+    <eg-grid-action 
+      label="[% l('Add Billing') %]" handler="addBilling"></eg-grid-action>
+    <eg-grid-action 
+      label="[% l('Full Details') %]" handler="showFullDetails"></eg-grid-action>
+
+    <eg-grid-field path="summary.balance_owed"></eg-grid-field>
+    <eg-grid-field path="id" label="[% l('Bill #') %]"></eg-grid-field>
+    <eg-grid-field path="xact_finish" label="[% l('Finish') %]"></eg-grid-field>
+    <eg-grid-field path="xact_start" label="[% l('Start') %]"></eg-grid-field>
+    <eg-grid-field path="summary.total_owed" label="[% l('Total Billed') %]"></eg-grid-field>
+    <eg-grid-field path="summary.total_paid" label="[% l('Total Paid') %]"></eg-grid-field>
+    <eg-grid-field path="summary.xact_type" label="[% l('Type') %]"></eg-grid-field>
+
+    <eg-grid-field label="[% l('Title') %]" name="title" 
+      path="circulation.target_copy.call_number.record.simple_record.title">
+      <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.record_id}}">{{item.title}}</a>
+    </eg-grid-field>
+
+    <!-- needed for bib link -->
+    <eg-grid-field name="record_id" 
+      path="circulation.target_copy.call_number.record.id" 
+      required hidden></eg-grid-field>
+
+    <eg-grid-field label="[% l('Barcode') %]" name="copy_barcode" 
+      path="circulation.target_copy.barcode">
+      <a target="_self" href="./cat/item/{{item.copy_id}}">{{item.copy_barcode}}</a>
+    </eg-grid-field>
+
+    <!-- needed for item link -->
+    <eg-grid-field name="copy_id" 
+      path="circulation.target_copy.id" required hidden></eg-grid-field>
+
+    <!-- needed for grid query -->
+    <eg-grid-field path="summary.last_payment_ts" required hidden></eg-grid-field>
+
+    <eg-grid-field path="summary.*" hidden></eg-grid-field>
+    <eg-grid-field path="circulation.target_copy.*" hidden></eg-grid-field>
+    <eg-grid-field path="circulation.target_copy.call_number.*" hidden></eg-grid-field>
+  </eg-grid>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_bills.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_bills.tt2
new file mode 100644 (file)
index 0000000..b8ab917
--- /dev/null
@@ -0,0 +1,109 @@
+
+<div class="row">
+  <div class="col-md-7">
+
+    <div class="row">
+      <div class="col-md-4">[% l('Total Owed:') %]</div>
+      <div class="col-md-2 strong-text">{{summary.balance_owed() | currency}}</div>
+      <div class="col-md-4">[% l('Refunds Available:') %]</div>
+      <div class="col-md-2">{{refunds_available() | currency}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Total Billed:') %]</div>
+      <div class="col-md-2">{{summary.total_owed() | currency}}</div>
+      <div class="col-md-4">[% l('Credit Available:') %]</div>
+      <div class="col-md-2">{{patron().credit_forward_balance() | currency}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Total Paid:') %]</div>
+      <div class="col-md-2">{{summary.total_paid() | currency}}</div>
+      <div class="col-md-4">[% l('Session Voided:') %]</div>
+      <div class="col-md-2">{{session_voided | currency}}</div>
+    </div>
+    <div class="row"><hr/></div>
+    <div class="row">
+      <div class="col-md-4">[% l('Owed for Selected:') %]</div>
+      <div class="col-md-2">{{owed_selected() | currency}}</div>
+      <div class="col-md-4">[% l('Pending Payment:') %]</div>
+      <div class="col-md-2 strong-text">{{pending_payment() | currency}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Billed for Selected:') %]</div>
+      <div class="col-md-2">{{billed_selected() | currency}}</div>
+      <div class="col-md-4">[% l('Pending Change:') %]</div>
+      <div class="col-md-2 strong-text">{{pending_change() | currency}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Paid for Selected:') %]</div>
+      <div class="col-md-2">{{paid_selected() | currency}}</div>
+    </div>
+  </div><!-- col -->
+
+  <div class="col-md-5">
+    <form role="form" class="form-horizontal" ng-submit="applyPayment()">
+      <fieldset>
+        <legend>[% l('Pay Bill') %]</legend>
+
+        <div class="form-group">
+          <label for="type-input" class="col-md-6 control-label">[% l('Payment Type') %]</label>
+          <div class="col-md-6">
+            <select ng-model="payment_type" class="form-control">
+              <option value="cash_payment" selected="selected">[% l('Cash') %]</option>
+              <option value="check_payment">[% l('Check') %]</option>
+              <option value="credit_card_payment">[% l('Credit Card') %]</option>
+              <option value="credit_payment">[% l('Patron Credit') %]</option>
+              <option value="work_payment">[% l('Work') %]</option>
+              <option value="forgive_payment">[% l('Forgive') %]</option>
+              <option value="goods_payment">[% l('Goods') %]</option>
+            </select>
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="amount-input" class="col-md-6 control-label">
+            [% l('Payment Received') %]
+          </label>
+          <div class="col-md-6">
+            <input type="number" min="0" step="any" id="amount-input" 
+              ng-model="payment_amount" focus-me="focus_payment" 
+              value="" class="form-control col-md-6 "/>
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="annotate-payment" class="control-label col-md-5">[% l('Annotate') %]</label>
+          <div class="col-md-1">
+            <input id="annotate-payment" type="checkbox" ng-model="annotate_payment"/>
+          </div>
+          <div class="col-md-6">
+            <button type="submit" class="btn btn-default">[% l('Apply Payment') %]</button>
+          </div>
+        </div>
+      </fieldset>
+    </form>
+  </div>
+</div>
+
+<div class="pad-vert">
+[% INCLUDE 'staff/circ/patron/t_bills_list.tt2' %]
+</div>
+
+<!-- pull-right is causing the content to flow several pixels 
+off to the right.  flex-row is honoring the boundaries better. 
+not sure what's up, there. -->
+<div class="flex-row">
+  <div class="flex-cell"></div>
+  <form class="form-inline" role="form">
+   <div class="checkbox">
+      <label>
+        <input type="checkbox" ng-model="receipt_on_pay"/> 
+        [% l('Receipt On Payment') %]
+      </label>
+    </div>
+    <div class="form-group" style="margin-left:10px">
+      <label for="bill-receipt-copies">[% l('# Copies') %]</label>
+      <input type="number" min="1" style="width:5em"
+        ng-model="receipt_count"
+        class="form-control" id="bill-receipt-copies"/>
+    </div>
+  </form>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2
new file mode 100644 (file)
index 0000000..c98d041
--- /dev/null
@@ -0,0 +1,87 @@
+
+<eg-grid
+  idl-class="mbt"
+  query="gridQuery"
+  sort="gridSort"
+  grid-controls="gridControls"
+  revision="gridRevision"
+  persist-key="circ.patron.bills">
+
+  <eg-grid-menu-item label="[% l('Bill Patron') %]" 
+    handler="showBillDialog"></eg-grid-menu-item>
+
+  <eg-grid-menu-item label="[% l('History') %]" 
+    handler="showHistory"></eg-grid-menu-item>
+
+  <eg-grid-menu-item label="[% l('Check All Refunds') %]" 
+    handler="selectRefunds"></eg-grid-menu-item>
+
+  <eg-grid-action label="[% l('Print Bills') %]" 
+    handler="printBills"></eg-grid-action>
+
+  <!--
+  need to decide if these are necessary here w/ inline links
+  to record and copy details (though they could be hidden).
+  it's misleading to allow the user to select multiple bills
+  but only open the link to one
+
+  <eg-grid-action label="[% l('Show in Catalog') %]" 
+    handler=""></eg-grid-action>
+
+  <eg-grid-action label="[% l('Show Item Details') %]" 
+    handler=""></eg-grid-action>
+  -->
+
+  <eg-grid-action label="[% l('Void All Billings') %]" 
+    handler="voidAllBillings"></eg-grid-action>
+
+  <eg-grid-action label="[% l('Refund') %]" 
+    handler="refundXact"></eg-grid-action>
+
+  <eg-grid-action label="[% l('Add Billing') %]" 
+    handler="addBilling"></eg-grid-action>
+
+  <eg-grid-action label="[% l('Full Details') %]" 
+    handler="showFullDetails"></eg-grid-action>
+
+  <eg-grid-field label="[% ('Balance Owed') %]" path='summary.balance_owed'></eg-grid-field>
+  <eg-grid-field label="[% ('Bill #') %]" path='id'></eg-grid-field>
+  <eg-grid-field label="[% ('Start') %]" path='xact_start'></eg-grid-field>
+  <eg-grid-field label="[% ('Total Billed') %]" path='summary.total_owed'></eg-grid-field>
+  <eg-grid-field label="[% ('Total Paid') %]" path='summary.total_paid'></eg-grid-field>
+  <eg-grid-field label="[% ('Type') %]" path='xact_type'></eg-grid-field>
+
+  <!-- receipt data -->
+  <eg-grid-field path='summary.last_billing_type' required></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]" name="title"
+    path='circulation.target_copy.call_number.record.simple_record.title'>
+    <a target="_self" href="[% ctx.base_path %]/staff/cat/catalog/record/{{item.record_id}}">{{item.title}}</a>
+  </eg-grid-field>
+  <!-- fetch the record ID so we can link to it.  hide it by default -->
+  <eg-grid-field path="circulation.target_copy.call_number.record.id" 
+    label="[% l('Record ID') %]" name="record_id" required hidden>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Barcode') %]" required
+    path='circulation.target_copy.barcode' name="copy_barcode">
+    <a href="./cat/item/{{item.copy_id}}" target="_self">
+      {{item.copy_barcode}}
+    </a>
+  </eg-grid-field>
+  <!-- fetch the copy ID so we can link to it.  hide it by default -->
+  <eg-grid-field path="circulation.target_copy.id" 
+    label="[% l('Copy ID') %]" name="copy_id" required hidden>
+  </eg-grid-field>
+
+  <!-- virtual field -->
+  <eg-grid-field datatype="money" label="[% ('Payment Pending') %]" 
+    name="payment_pending"></eg-grid-field>
+
+  <!-- import all circ fields, hidden by default -->
+  <eg-grid-field path='circulation.*' hidden> </eg-grid-field>
+
+  <eg-grid-field path='circulation.target_copy.*' hidden> </eg-grid-field>
+  
+</eg-grid>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
new file mode 100644 (file)
index 0000000..945f2db
--- /dev/null
@@ -0,0 +1,143 @@
+<!-- item checkout form / list -->
+
+<div class="row pad-vert">
+  <div class="col-md-6">
+    <form ng-submit="checkout(checkoutArgs)" role="form" class="form-inline">
+      <div class="input-group">
+
+        <div class="input-group-btn" dropdown>
+          <button type="button" class="btn btn-default dropdown-toggle"
+            ng-class="{disabled : disable_checkout()}">
+            {{selectedNcType() || "[% l('Barcode') %]"}}
+            <span class="caret"></span>
+          </button>
+          <ul class="dropdown-menu">
+            <li><a href dropdown-toggle
+              ng-click="checkoutArgs.noncat_type='barcode';focusMe=true">
+              [% l('Barcode') %]</a>
+            </li>
+            <li class="divider"></li>
+            <li>
+              <a href ng-repeat='type in nonCatTypes' dropdown-toggle
+               ng-click="checkoutArgs.noncat_type=type.id()">{{type.name()}}</a>
+            </li>
+          </ul>
+        </div>
+
+        <input focus-me="focusMe" class="form-control"
+          ng-model="checkoutArgs.copy_barcode" 
+          ng-disabled="checkoutArgs.noncat_type != 'barcode' || disable_checkout()"
+          id="patron-checkout-barcode" type="text"/> 
+
+        <input class="btn btn-default" type="submit" 
+          ng-class="{disabled : disable_checkout()}" value="[% l('Submit') %]"/>
+
+      </div>
+    </form>
+  </div>
+  <div class="col-md-6">
+    <div class="flex-row">
+      <div class="flex-cell"></div>
+      <div class="checkbox pad-horiz">
+        <label>
+          <input type="checkbox" ng-model="checkoutArgs.sticky_date"/>
+          [% l('Specific Due Date') %]
+        </label>
+      </div>
+      <!--
+      <div><input type="checkbox" class="checkbox" ng-model="checkoutArgs.sticky_date"/></div>
+      <div class="pad-horiz">[% l('Specific Due Date') %]</div>
+      -->
+      <!-- FIXME: This needs a time component as well, but type="datetime" 
+            is not yet supported by any browsers -->
+      <div><input eg-date-input class="form-control" 
+        ng-model="checkoutArgs.due_date"/>
+      </div>
+    </div>
+  </div>
+</div>
+<hr/>
+
+<eg-grid
+  id-field="index"
+  features="-sort,-multisort"
+  items-provider="gridDataProvider"
+  grid-controls="gridControls"
+  persist-key="circ.patron.checkout">
+
+  <eg-grid-field label="[% l('Alert Msg') %]"   
+    path="acp.alert_message"></eg-grid-field>
+
+  <eg-grid-field label="[% l('Balance Owed') %]"     
+    path='mbts.balance_owed'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Barcode') %]" path="acp_barcode">
+    <!-- FIXME: ng-if / ng-disabled not working since the contents 
+        are $interpolate'd and not $compile'd.
+        I want to hide / disable the href when there is no acp ID 
+    -->
+    <a href="./cat/item/{{item.acp.id()}}/summary" target="_self">
+      {{item.copy_barcode}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Bill #') %]"     
+    path='circ.id'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Call Number') %]" 
+    path="acn.label"></eg-grid-field>
+
+  <eg-grid-field label="[% l('Due Date') %]"    
+    path='circ.due_date' dateformat='short'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Family Name') %]"    
+    path='au.family_name'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Location') %]" 
+    path='acp.location.name'> </eg-grid-field>
+
+  <eg-grid-field label="[% l('Remaining Renewals') %]" 
+    path='circ.renewal_remaining'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]" path="title">
+    <a target="_self" href="[% ctx.base_path %]/opac/record/{{record.doc_id()}}">
+      {{item.title}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Author') %]"      
+    path="author" hidden></eg-grid-field>
+
+  <eg-grid-field path="circ.*" parent-idl-class="circ" hidden></eg-grid-field>
+  <eg-grid-field path="acp.*" parent-idl-class="acp" hidden></eg-grid-field>
+  <eg-grid-field path="acn.*" parent-idl-class="acn" hidden></eg-grid-field>
+  <eg-grid-field path="record.*" parent-idl-class="mvr" hidden></eg-grid-field>
+  <eg-grid-field path="mbts.*" parent-idl-class="mbts" hidden></eg-grid-field>
+  <eg-grid-field path="au.*" parent-idl-class="au" hidden></eg-grid-field>
+</eg-grid>
+
+<div class="flex-row pad-vert">
+  <div class="flex-cell"></div>
+  <div class="checkbox">
+    <label>
+      <input ng-model="strict_barcode" type="checkbox"/>
+      [% l('Strict Barcode') %]
+    </label>
+  </div>
+  <div class="pad-horiz" ng-if="using_hatch"></div>
+  <div class="checkbox" ng-if="using_hatch">
+    <label>
+      <input ng-model="show_print_dialog" type="checkbox"/>
+      [% l('Show Print Dialog') %]
+    </label>
+  </div>
+  <div class="pad-horiz">
+    <button class="btn btn-default" 
+      ng-click="print_receipt()">[% l('Print Receipt') %]</button>
+  </div>
+  <div>
+    <button class="btn btn-default" 
+      ng-click="done()">[% l('Done') %]</button>
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_credentials.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_credentials.tt2
new file mode 100644 (file)
index 0000000..524cb7f
--- /dev/null
@@ -0,0 +1,65 @@
+<div class="container">
+  <div class="row">
+    <div class="col-md-6">
+      <fieldset>
+        <legend>[% l('Verify Credentials') %]</legend>
+        <form ng-submit="verify()" 
+          name="verify-creds-form" class="form-horizontal" role="form">
+
+          <div class="form-group">
+            <label class="col-md-4 control-label" 
+              for="verify-username">[% l('Username') %]</label>
+            <div class="col-md-8">
+              <input type="text" id="verify-username" class="form-control" 
+                focus-me="focusMe" ng-disabled="prepop"
+                placeholder="[% l('Username') %]" ng-model="username"/>
+            </div>
+          </div>
+
+          <div class="form-group">
+            <label class="col-md-4 control-label" 
+              for="verify-barcode">[% l('Barcode') %]</label>
+            <div class="col-md-8">
+              <input type="text" id="verify-barcode" class="form-control" 
+                ng-disabled="prepop"
+                placeholder="[% l('Barcode') %]" ng-model="barcode"/>
+            </div>
+          </div>
+
+          <div class="form-group">
+            <label class="col-md-4 control-label" 
+              for="verify-password">[% l('Password') %]</label>
+            <div class="col-md-8">
+              <input type="password" id="verify-password" class="form-control" 
+                placeholder="[% l('Password') %]" ng-model="password"/>
+            </div>
+          </div>
+
+          <div class="form-group">
+            <div class="col-md-offset-4 col-md-2">
+              <button type="submit" class="btn btn-default">[% l('Verify') %]</button>
+            </div>
+            <div class="col-md-2" ng-hide="prepop">
+              <button class="btn btn-default" ng-click="load($event)">[% l('Retrieve') %]</button>
+            </div>
+          </div>
+
+          <div class="form-group" ng-cloak>
+            <div class="col-md-offset-4 col-md-8">
+              <div class="alert alert-success" ng-show="verified">
+                [% l('Succes testing credentials') %]
+              </div>
+              <div class="alert alert-danger" ng-show="verified === false">
+                [% l('Failure testing credentials') %]
+              </div>
+              <div class="alert alert-danger" ng-show="notFound">
+                [% l('No user found with the requested username / barcode') %]
+              </div>
+            </div>
+          </div>
+
+        </form>
+      </fieldset>
+    <div><!-- col -->
+  </div><!-- row -->
+</div><!-- container -->
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2
new file mode 100644 (file)
index 0000000..3f85366
--- /dev/null
@@ -0,0 +1,2 @@
+<eg-embed-frame url="patron_edit_url" handlers="funcs"></eg-embed-frame>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_edit_due_date_dialog.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_edit_due_date_dialog.tt2
new file mode 100644 (file)
index 0000000..dcca6d3
--- /dev/null
@@ -0,0 +1,24 @@
+<form ng-submit="ok(args)" role="form">
+  <div class="modal-header">
+    <button type="button" class="close" ng-click="cancel()" 
+      aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Edit Due Date For [_1] Items', '{{args.num_circs}}') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="form-group row pad-vert">
+      <div class="col-md-6">
+        [% l('Enter Due Date: ') %]
+      </div>
+      <div class="col-md-6">
+        <input eg-date-input class="form-control" ng-model="args.due_date"/>
+      </div>
+    </div>
+    <!-- TODO: time picker -->
+  </div>
+  <div class="modal-footer">
+    <input type="submit" class="btn btn-primary" value="[% l('OK') %]"/>
+    <button class="btn btn-warning" ng-click="cancel($event)">[% l('Cancel') %]</button>
+  </div>
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_edit_perms.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_edit_perms.tt2
new file mode 100644 (file)
index 0000000..76d10f6
--- /dev/null
@@ -0,0 +1 @@
+<eg-embed-frame url="user_perms_url" handlers="funcs"></eg-embed-frame>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_group.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_group.tt2
new file mode 100644 (file)
index 0000000..21bb4c2
--- /dev/null
@@ -0,0 +1,55 @@
+
+<div class="strong-text-2">[% l('Group Member Details') %]</div>
+<div class="pad-vert flex-row">
+  <div>[% l('Total Owed: ') %]</div>
+  <div class="pad-horiz">{{totals.owed | currency}}</div>
+  <div>[% l('Total Out: ') %]</div>
+  <div class="pad-horiz">{{totals.total_out}}</div>
+  <div>[% l('Total Overdue: ') %]</div>
+  <div class="pad-horiz">{{totals.overdue}}</div>
+</div>
+<div class="pad-vert"></div>
+<eg-grid
+  idl-class="au"
+  sort="gridSort"
+  grid-controls="gridControls"
+  menu-label="[% l('Group Actions') %]">
+
+  <eg-grid-menu-item handler="moveToGroup"
+    label="[% l('Move Another Patron To This Group') %]"></eg-grid-menu-item>
+
+  <eg-grid-action 
+    label="[% l('Register a New Group Member by Cloning Selected Patron') %]" 
+    handler="cloneUser"></eg-grid-action>
+
+  <eg-grid-action label="[% l('Remove Selected From Group') %]" 
+    handler="removeFromGroup"></eg-grid-action>
+
+  <eg-grid-action label="[% l("Move Selected Patrons to Another Patron's Group") %]" 
+    handler="moveToAnotherGroup"></eg-grid-action>
+
+  <eg-grid-action label="[% l("Retrieve Selected Patron") %]" 
+    handler="retrieveSelected"></eg-grid-action>
+
+  <eg-grid-field path="active"></eg-grid-field>
+  <eg-grid-field path="barred"></eg-grid-field>
+  <eg-grid-field path="dob"></eg-grid-field>
+  <eg-grid-field path="family_name"></eg-grid-field>
+  <eg-grid-field path="first_given_name"></eg-grid-field>
+  <eg-grid-field path="master_account"></eg-grid-field>
+  <eg-grid-field path="second_given_name"></eg-grid-field>
+  <eg-grid-field path="stats.fines.balance_owed" nonsortable label="[% l('Balance Owed') %]"></eg-grid-field>
+  <eg-grid-field path="stats.checkouts.out" nonsortable label="[% l('Items Out') %]"></eg-grid-field>
+  <eg-grid-field path="stats.checkouts.overdue" nonsortable label="[% l('Items Overdue') %]"></eg-grid-field>
+
+  <!-- needed for query, sorting -->
+  <eg-grid-field path="id" hidden required></eg-grid-field>
+  <eg-grid-field path="usrgroup" hidden required></eg-grid-field>
+  <eg-grid-field path="deleted" hidden required></eg-grid-field>
+  <eg-grid-field path="create_date" hidden required></eg-grid-field>
+
+  <!--
+  <eg-grid-field path=".*"></eg-grid-field>
+  -->
+
+</eg-grid>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_holds.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_holds.tt2
new file mode 100644 (file)
index 0000000..5ccd762
--- /dev/null
@@ -0,0 +1,38 @@
+<!-- patron holds list -->
+
+<ul class="nav nav-tabs" ng-if="!detail_hold_id">
+  <li ng-class="{active : holds_display == 'main', disabled : detail_hold_id}">
+    <a href ng-click="show_main_list()">[% l('Open Hold Requests') %]</a>
+  </li>
+  <li ng-class="{active : holds_display == 'alt', disabled : detail_hold_id}">
+    <a href ng-click="show_alt_list()">[% l('Recently Canceled Holds') %]</a>
+  </li>
+</ul>
+
+<div class="pad-vert"></div>
+
+<div ng-if="!detail_hold_id">
+[% INCLUDE 'staff/circ/patron/t_holds_list.tt2' %]
+</div>
+
+<!-- hold details -->
+<div ng-if="detail_hold_id">
+  <div class="row">
+    <div class="col-md-2">
+      <button class="btn btn-default" ng-click="list_view()">
+        [% l('List View') %]
+      </button>
+    </div>
+  </div>
+  <div class="pad-vert"></div>
+  <eg-record-summary record='detail_hold_record' 
+    record-id="detail_hold_record_id"></eg-record-summary>
+  <eg-hold-details hold-retrieved="set_hold" hold-id="detail_hold_id"></eg-hold-details>
+</div>
+
+<!-- catalog view for holds placement -->
+
+<div ng-if="placing_hold">
+  <eg-embed-frame url="catalog_url" handlers="handlers" 
+    onchange="handle_page"></eg-embed-frame>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_holds_create.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_holds_create.tt2
new file mode 100644 (file)
index 0000000..e8e82e4
--- /dev/null
@@ -0,0 +1,4 @@
+<!-- holds are created within the catalog -->
+
+<eg-embed-frame url="catalog_url" 
+  handlers="handlers" onchange="handle_page"></eg-embed-frame>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_holds_list.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_holds_list.tt2
new file mode 100644 (file)
index 0000000..df026fa
--- /dev/null
@@ -0,0 +1,82 @@
+<eg-grid
+  id-field="id"
+  features="-sort,-multisort"
+  items-provider="gridDataProvider"
+  persist-key="circ.patron.holds">
+
+  <eg-grid-menu-item handler="place_hold" 
+    label="[% l('Place Hold') %]"></eg-grid-menu-item>
+  <eg-grid-menu-item handler="detail_view" 
+    label="[% l('Detail View') %]"></eg-grid-menu-item>
+
+  <eg-grid-action handler="grid_actions.show_recent_circs"
+    label="[% l('Show Last Few Circulations') %]"></eg-grid-action>
+  <eg-grid-action divider="true"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.set_copy_quality"
+    label="[% l('Set Desired Copy Quality') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_pickup_lib"
+    label="[% l('Edit Pickup Library') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_notify_prefs"
+    label="[% l('Edit Notification Settings') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.edit_dates"
+    label="[% l('Edit Hold Dates') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.activate"
+    label="[% l('Activate') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.suspend"
+    label="[% l('Suspend') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.set_top_of_queue"
+    label="[% l('Set Top of Queue') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.clear_top_of_queue"
+    label="[% l('Un-Set Top of Queue') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.transfer_to_marked_title"
+    label="[% l('Transfer To Marked Title') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.mark_damaged"
+    label="[% l('Mark Item Damaged') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.mark_missing"
+    label="[% l('Mark Item Missing') %]"></eg-grid-action>
+  <eg-grid-action divider="true"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.retarget"
+    label="[% l('Find Another Target') %]"></eg-grid-action>
+  <eg-grid-action handler="grid_actions.cancel_hold"
+    label="[% l('Cancel Hold') %]"></eg-grid-action>
+
+  <eg-grid-field label="[% l('Hold ID') %]" path='hold.id'></eg-grid-field>
+  <eg-grid-field label="[% l('Current Copy') %]" 
+    path='hold.current_copy.barcode'>
+    <a href="./cat/item/{{item.hold.current_copy().id()}}/summary" target="_self">
+      {{item.hold.current_copy().barcode()}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Request Date') %]" path='hold.request_time'></eg-grid-field>
+  <eg-grid-field label="[% l('Capture Date') %]" path='hold.capture_time'></eg-grid-field>
+  <eg-grid-field label="[% l('Available Date') %]" path='hold.shelf_time'></eg-grid-field>
+  <eg-grid-field label="[% l('Hold Type') %]" path='hold.hold_type'></eg-grid-field>
+  <eg-grid-field label="[% l('Pickup Library') %]" path='hold.pickup_lib.shortname'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]" path='mvr.title'>
+    <a href="[% ctx.base_path %]/opac/record/{{item.mvr.doc_id()}}">
+      {{item.mvr.title()}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Author') %]" path='mvr.author'></eg-grid-field>
+  <eg-grid-field label="[% l('Potential Copies') %]" path='potential_copies'></eg-grid-field>
+  <eg-grid-field label="[% l('Status') %]" path='status_string'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Queue Position') %]" path='queue_position' hidden></eg-grid-field>
+  <eg-grid-field path='hold.*' parent-idl-class="ahr" hidden></eg-grid-field>
+  <eg-grid-field path='copy.*' parent-idl-class="acp" hidden></eg-grid-field>
+  <eg-grid-field path='volume.*' parent-idl-class="acn" hidden></eg-grid-field>
+  <eg-grid-field path='mvr.*' parent-idl-class="mvr" hidden></eg-grid-field>
+</eg-grid>
+
+<div class="flex-row pad-vert">
+  <div class="flex-cell"></div>
+  <div>
+    <button class="btn btn-default" ng-click="print()">
+      [% l('Print') %]
+    </button>
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_items_out.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_items_out.tt2
new file mode 100644 (file)
index 0000000..71fc1a0
--- /dev/null
@@ -0,0 +1,73 @@
+<!-- items out list -->
+
+<div ng-if="show_alt_circs">
+  <!-- only show the main vs. alt circ list tabs if the alt
+      circ list is meant to display -->
+  <ul class="nav nav-tabs">
+    <li ng-class="{active : items_out_display == 'main'}">
+      <a href ng-click="show_main_list()">
+        [% l('Items Checked Out') %] ({{main_list.length}})
+      </a>
+    </li>
+    <li ng-class="{active : items_out_display == 'alt'}">
+      <a href ng-click="show_alt_list()">
+        [% l('Other/Special Circulations') %] ({{alt_list.length}})
+      </a>
+    </li>
+  </ul>
+</div>
+<div ng-if="!show_alt_circs" class="strong-text-2">
+  [% l('Items Checked Out') %]
+</div>
+
+<div class="tab-content">
+  <div class="tab-pane active">
+<eg-grid
+  idl-class="circ"
+  id-field="id"
+  features="-sort,-multisort"
+  items-provider="gridDataProvider"
+  persist-key="circ.patron.items_out">
+
+  <eg-grid-action handler="print_receipt"
+    label="[% l('Print Item Receipt') %]"></eg-grid-action>
+  <eg-grid-action handler="edit_due_date"
+    label="[% l('Edit Due Date') %]"></eg-grid-action>
+  <eg-grid-action handler="mark_lost"
+    label="[% l('Mark Lost (By Patron)') %]"></eg-grid-action>
+  <eg-grid-action handler="mark_claims_returned"
+    label="[% l('Mark Claims Returned') %]"></eg-grid-action>
+  <eg-grid-action handler="mark_claims_never_checked_out"
+    label="[% l('Mark Claims Never Checked Out') %]"></eg-grid-action>
+  <eg-grid-action handler="renew" label="[% l('Renew') %]"></eg-grid-action>
+  <eg-grid-action handler="renew_all" label="[% l('Renew All') %]"></eg-grid-action>
+  <eg-grid-action handler="renew_with_date" 
+    label="[% l('Renew With Specific Due Date') %]"></eg-grid-action>
+  <eg-grid-action handler="checkin" 
+    label="[% l('Check In') %]"></eg-grid-action>
+  <eg-grid-action handler="add_billing" 
+    label="[% l('Add Billing') %]"></eg-grid-action>
+
+  <eg-grid-field label="[% l('Circ ID') %]" path='id'></eg-grid-field>
+  <eg-grid-field label="[% l('Barcode') %]" path='target_copy.barcode'>
+    <a href="./cat/item/{{item.target_copy().id()}}" target="_self">
+      {{item.target_copy().barcode()}}
+    </a>
+  </eg-grid-field>
+  <eg-grid-field label="[% l('Due Date') %]" path='due_date' dateformat='short'></eg-grid-field>
+  <eg-grid-field label="[% l('Checkout / Renewal Library') %]" path='circ_lib.shortname'></eg-grid-field>
+  <eg-grid-field label="[% l('Renewals Remaining') %]" path='renewal_remaining'></eg-grid-field>
+  <eg-grid-field label="[% l('Fines Stopped') %]" path='stop_fines'></eg-grid-field>
+  <eg-grid-field label="[% l('Title') %]" name="title">
+    <a href="[% ctx.base_path %]/opac/record/{{item.target_copy().call_number().record().id()}}">
+      {{item.target_copy().call_number().record().simple_record().title()}}
+    </a>
+  </eg-grid-field>
+  <eg-grid-field path="*" hidden></eg-grid-field>
+  <eg-grid-field path="target_copy.*" hidden></eg-grid-field>
+  <eg-grid-field path="target_copy.call_number.*" hidden></eg-grid-field>
+  <eg-grid-field path="target_copy.call_number.record.*" hidden></eg-grid-field>
+  <eg-grid-field path="target_copy.call_number.record.simple_record.*" hidden></eg-grid-field>
+</eg-grid>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_last_patron.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_last_patron.tt2
new file mode 100644 (file)
index 0000000..9a917d8
--- /dev/null
@@ -0,0 +1,9 @@
+<div class="col-md-6">
+  <div ng-if="no_last" class="alert alert-warning">
+    [% l('No patrons recently accessed.') %]
+    <span class="pad-horiz">
+      <a href='./circ/patron/search'>[% l('Try Patron Search') %]</a>
+    </span>
+  </div>
+  <br/>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_messages.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_messages.tt2
new file mode 100644 (file)
index 0000000..e23c258
--- /dev/null
@@ -0,0 +1,52 @@
+
+<div class="strong-text-2">[% l('Staff-Generated Penalties / Messages') %]</div>
+<div class="pad-vert"></div>
+<eg-grid
+  idl-class="ausp"
+  grid-controls="activeGridControls">
+
+  <eg-grid-menu-item handler="createPenalty"
+    label="[% l('Apply Penalty / Message') %]"></eg-grid-menu-item>
+
+  <eg-grid-action label="[% l('Remove Penalty / Message') %]" 
+    handler="removePenalty"></eg-grid-action>
+  <eg-grid-action label="[% l('Modify Penalty / Message') %]" 
+    handler="editPenalty"></eg-grid-action>
+  <eg-grid-action label="[% l('Archive Penalty / Message') %]" 
+    handler="archivePenalty"></eg-grid-action>
+
+  <eg-grid-field path="set_date" label="[% l('Applied On') %]"></eg-grid-field>
+  <eg-grid-field path="standing_penalty.label"></eg-grid-field>
+  <eg-grid-field path="org_unit.shortname" label="[% l('Library') %]"></eg-grid-field>
+  <eg-grid-field path="note"></eg-grid-field>
+  <eg-grid-field path="id" required hidden></eg-grid-field>
+  <eg-grid-field path="standing_penalty.block_list" required hidden></eg-grid-field>
+  <eg-grid-field path="standing_penalty.*" hidden></eg-grid-field>
+
+</eg-grid>
+
+<div class="pad-vert"><hr/></div>
+
+<div class="pad-vert flex-row padded">
+  <div class="strong-text-2">[% l('Archived Penalties / Messages') %]</div>
+  <div class="flex-cell"></div>
+  <div>[% l('Set Date Start:') %]</div>
+  <div><input eg-date-input class="form-control" ng-model="dates.start_date"/></div>
+  <div>[% l('Set Date End:') %]</div>
+  <div><input eg-date-input class="form-control" ng-model="dates.end_date"/></div>
+</div>
+<eg-grid
+  idl-class="ausp"
+  grid-controls="archiveGridControls">
+
+  <eg-grid-field path="set_date" label="[% l('Applied On') %]"></eg-grid-field>
+  <eg-grid-field path="standing_penalty.label"></eg-grid-field>
+  <eg-grid-field path="org_unit.shortname" label="[% l('Library') %]"></eg-grid-field>
+  <eg-grid-field path="note"></eg-grid-field>
+  <eg-grid-field path="id" required hidden></eg-grid-field>
+  <eg-grid-field path="standing_penalty.block_list" required hidden></eg-grid-field>
+  <eg-grid-field path="standing_penalty.*" hidden></eg-grid-field>
+
+</eg-grid>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_move_to_group_dialog.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_move_to_group_dialog.tt2
new file mode 100644 (file)
index 0000000..96e9733
--- /dev/null
@@ -0,0 +1,28 @@
+<div>
+  <div class="modal-header">
+    <button type="button" class="close" ng-click="cancel()" 
+      aria-hidden="true">&times;</button>
+    <h4 ng-if="!outbound" class="modal-title">
+      [% l('Move user into this group?') %]
+    </h4>
+    <h4 ng-if="outbound" class="modal-title">
+      [% l("Move selected users to the following user's group?") %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <a href="./circ/patron/{{user.id()}}/checkout" target="_self">
+      [% 
+        l('[_1], [_2] [_3] : [_4]', 
+          '{{user.family_name()}}',
+          '{{user.first_given_name()}}',
+          '{{user.second_given_name()}}',
+          '{{user.card().barcode()}}') 
+      %]
+    </a>
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-primary" ng-click="ok()">[% l('Move User') %]</button>
+    <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_new_note_dialog.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_new_note_dialog.tt2
new file mode 100644 (file)
index 0000000..cfc5b40
--- /dev/null
@@ -0,0 +1,42 @@
+<form ng-submit="ok(args)" role="form">
+    <div class="modal-header">
+      <button type="button" class="close" ng-click="cancel()" 
+        aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Create a new note') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-title">[% l('Title') %]</label>
+        </div>
+        <div class="col-md-9">
+          <input type="text" class="form-control" focus-me='focusNote' required
+            id="note-title" ng-model="args.title" placeholder="[% l('Title...') %]"/>
+        </div>
+      </div>
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-pub">[% l('Patron Visible?') %]</label>
+        </div>
+        <div class="col-md-9">
+          <input type="checkbox" class="checkbox" 
+            id="note-pub" ng-model="args.pub"/>
+        </div>
+      </div>
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-value">[% l('Value') %]</label>
+        </div>
+        <div class="col-md-9">
+          <textarea class="form-control" required
+            id="note-value" ng-model="args.value" placeholder="[% l('Value...') %]">
+          </textarea>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-primary" value="[% l('OK') %]"/>
+      <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+    </div>
+  </div> <!-- modal-content -->
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_notes.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_notes.tt2
new file mode 100644 (file)
index 0000000..b83f317
--- /dev/null
@@ -0,0 +1,44 @@
+<div class="row">
+  <div class="col-md-12">
+    <button class="btn btn-default" ng-click="newNote()">
+      [% l('Add New Note') %]
+    </button>
+  </div>
+</div>
+
+<div class="row pad-vert" ng-repeat="note in notes">
+  <div class="col-md-12">
+    <div class="row">
+      <div class="col-md-6 strong-text">{{note.title()}}</div>
+      <div class="col-md-6">
+        <div class="pull-right">
+          <span class="pad-horiz alert alert-warning" ng-if="note.pub() == 't'">[% l('Patron Visible') %]</span>
+          <span class="pad-horiz alert alert-info" ng-if="note.pub() == 'f'">[% l('Staff Only') %]</span>
+          <span class="pad-horiz">{{note.create_date() | date:'short'}}</span>
+          <span>[% l('Created by [_1]', '{{note.creator().usrname()}}') %]</span>
+        </div>
+      </div>
+    </div>
+    <div class="row">
+      <!-- hmm, not sure why the margin-left is needed.. the well? -->
+      <div class="col-md-12 well" style="margin-left:12px">
+        <div class="row">
+          <div class="col-md-8">
+            <div class="">{{note.value()}}</div>
+          </div>
+          <div class="col-md-4">
+            <div class="pull-right">
+              <button ng-click="printNote(note)" class="btn btn-default">
+                [% l('Print') %]
+              </button>
+              <button ng-click="deleteNote(note)" class="btn btn-warning">
+                [% l('Delete') %]
+              </button>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <hr/>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_pending_list.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_pending_list.tt2
new file mode 100644 (file)
index 0000000..3809d12
--- /dev/null
@@ -0,0 +1,34 @@
+<div class="container-fluid" style="text-align:center">
+  <div class="alert alert-info alert-less-pad strong-text-2">
+    <span>[% l('Pending Patrons') %]</span>
+  </div>
+</div>
+
+<span>[% l('Home Library: ' ) %]</span>
+<span><eg-org-selector selected="context_org"></eg-org-selector></span>
+<hr/>
+
+<eg-grid
+  id-field="id"
+  features="-sort,-multisort"
+  items-provider="grid_data_provider"
+  grid-controls="grid_controls"
+  persist-key="circ.pending_patrons.list">
+
+  <eg-grid-menu-item handler="load_patron" 
+    label="[% l('Load Patron') %]"></eg-grid-menu-item>
+
+  <eg-grid-field path='user.row_date' label="[% l('Create Date') %]"></eg-grid-field>
+  <eg-grid-field path='user.first_given_name' label="[% l('First Name') %]"></eg-grid-field>
+  <eg-grid-field path='user.second_given_name' label="[% l('Middle Name') %]"></eg-grid-field>
+  <eg-grid-field path='user.family_name' label="[% l('Last Name') %]"></eg-grid-field>
+  <eg-grid-field path='user.email' label="[% l('Email') %]"></eg-grid-field>
+  <eg-grid-field path='user.home_ou.shortname' label="[% l('Home Library') %]"></eg-grid-field>
+  <eg-grid-field path='mailing_address.street1' label="[% l('Street 1') %]"></eg-grid-field>
+  <eg-grid-field path='mailing_address.city' label="[% l('City') %]"></eg-grid-field>
+  <eg-grid-field path='mailing_address.post_code' label="[% l('Post Code') %]"></eg-grid-field>
+  <eg-grid-field path='user.usrname' label="[% l('Requested Username') %]"></eg-grid-field>
+  <eg-grid-field path='user.*' parent-idl-class="stgu" hidden></eg-grid-field>
+  <eg-grid-field path='mailing_address.*' parent-idl-class="stgma" hidden></eg-grid-field>
+</eg-grid>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_renew_with_date_dialog.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_renew_with_date_dialog.tt2
new file mode 100644 (file)
index 0000000..d8112d0
--- /dev/null
@@ -0,0 +1,24 @@
+<div class="modal-header">
+  <button type="button" class="close" 
+    ng-click="cancel()" aria-hidden="true">&times;</button>
+  <h4 class="modal-title">
+    [% l('Renew Items with Specific Due Date') %]
+  </h4>
+</div>
+<div class="modal-body">
+  <div class="pad-vert row">
+    <div class="col-md-12">
+      [% l('Enter due date for items: [_1]', '{{args.barcodes.join(" ")}}') %]
+    </div>
+  </div>
+  <div class="pad-vert row">
+    <div class="col-md-5">
+      <input eg-date-input required 
+        class="form-control" ng-model="args.date"/>
+    </div>
+  </div>
+</div>
+<div class="modal-footer">
+  <button class="btn btn-primary" ng-click="ok()">[% l('Submit') %]</button>
+  <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_search.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_search.tt2
new file mode 100644 (file)
index 0000000..29abb40
--- /dev/null
@@ -0,0 +1,158 @@
+
+<!-- TODO: inputs need sr-only labels
+   <label class="sr-only" for="input-id">label</label>
+-->
+
+<div class="row" id="patron-search-form-row">
+  <div class="col-md-11">
+    <form ng-submit="search(searchArgs)" id="patron-search-form" 
+        role="form" class="form-horizontal">
+
+      <div class="form-group">
+
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            focus-me="focusMe"
+            ng-model="searchArgs.family_name" placeholder="[% l('Last Name') %]"/>
+        </div>
+
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.first_given_name" placeholder="[% l('First Name') %]"/>
+        </div>
+
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.second_given_name" placeholder="[% l('Middle Name') %]"/>
+        </div>
+
+        <div class="col-md-2">
+          <input type="submit" class="btn btn-default" value="[% l('Search') %]"/>
+        </div>
+
+        <div class="col-md-2">
+          <input type="reset" class="btn btn-default" ng-click="searchArgs={}" 
+            value="[% l('Clear Form') %]"/>
+        </div>
+
+        <div class="col-md-2">
+          <button class="btn btn-default" ng-click="applyShowExtras($event, true)" 
+            title="[% l('Show More Fields') %]" ng-show="!showExtras">
+            <span class="glyphicon glyphicon-circle-arrow-down"></span>
+          </button>
+          <button class="btn btn-default" ng-click="applyShowExtras($event, false)" 
+            title="[% l('Show Fewer Fields') %]" ng-show="showExtras">
+            <span class="glyphicon glyphicon-circle-arrow-up"></span>
+          </button>
+        </div>
+      </div>
+
+      <div class="form-group" ng-show="showExtras">
+        <div class="col-md-2">
+          <input type="text" class="form-control" ng-model="searchArgs.card" 
+            placeholder="[% l('Barcode') %]"/>
+        </div>
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.alias" placeholder="[% l('Alias') %]"/>
+        </div>
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.usrname" placeholder="[% l('Username') %]"/>
+        </div>
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.email" placeholder="[% l('Email') %]"/>
+        </div>
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.ident" placeholder="[% l('Identification') %]"/>
+        </div>
+      </div>
+
+      <div class="form-group" ng-show="showExtras">
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.id" placeholder="[% l('Database ID') %]"/>
+        </div>
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.phone" placeholder="[% l('Phone') %]"/>
+        </div>
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.street1" placeholder="[% l('Street 1') %]"/>
+        </div>
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.street2" placeholder="[% l('Street 2') %]"/>
+        </div>
+        <div class="col-md-2">
+          <input type="text" class="form-control" 
+            ng-model="searchArgs.city" placeholder="[% l('City') %]"/>
+        </div>
+      </div>
+
+      <div class="form-group" ng-show="showExtras">
+        <div class="col-md-2">
+          <input type="text" class="form-control" ng-model="searchArgs.state" 
+            placeholder="[% l('State') %]" title="[% l('State') %]"/>
+        </div>
+
+        <div class="col-md-2">
+          <input type="text" class="form-control" ng-model="searchArgs.post_code" 
+            placeholder="[% l('Post Code') %]" title="[% l('Post Code') %]"/>
+        </div>
+
+        <div class="col-md-2">
+          <!--
+          <input type="text" class="form-control"  
+            placeholder="[% l('Profile Group') %]"
+            ng-model="searchArgs.profile"
+            typeahead="grp as grp.name for grp in profiles | filter:$viewValue" 
+            typeahead-editable="false" />
+            -->
+
+            <div class="btn-group patron-search-selector" dropdown>
+              <button type="button" class="btn btn-default dropdown-toggle">
+                <span style="padding-right: 5px;">{{searchArgs.profile.name() || "[% l('Profile Group') %]"}}</span>
+                <span class="caret"></span>
+              </button>
+              <ul class="dropdown-menu">
+                <li ng-repeat="grp in profiles">
+                  <a href dropdown-toggle
+                    style="padding-left: {{pgt_depth(grp) * 10 + 5}}px"
+                    ng-click="searchArgs.profile = grp">{{grp.name()}}</a>
+                </li>
+              </ul>
+            </div>
+        </div>
+
+        <div class="col-md-2">
+          <eg-org-selector label="[% l('Home Library') %]" 
+            selected="searchArgs.home_ou">
+          </eg-org-selector>
+        </div>
+
+        <div class="col-md-2">
+          <div class="checkbox">
+            <label>
+              <input type="checkbox" ng-model="searchArgs.inactive"/>
+              [% l('Include Inactive?') %]
+            </label>
+          </div>
+        </div>
+      </div>
+    </form>
+  </div>
+</div>
+
+
+<br/>
+<div class="row">
+  <div class="col-md-12">
+    [% INCLUDE 'staff/circ/patron/t_search_results.tt2' %]
+  </div>
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_search_results.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_search_results.tt2
new file mode 100644 (file)
index 0000000..ac83e6d
--- /dev/null
@@ -0,0 +1,30 @@
+<eg-grid
+  idl-class="au" id-field="id"
+  features="-sort,-display,-multisort"
+  main-label="[% l('Patron Search Results') %]"
+  grid-controls="gridControls"
+  items-provider="patronSearchGridProvider"
+  persist-key="circ.patron.search">
+  <eg-grid-field label="[% ('ID') %]" path='id' visible></eg-grid-field>
+  <eg-grid-field label="[% ('Card') %]" path='card.barcode' visible></eg-grid-field>
+  <eg-grid-field label="[% ('Last Name') %]" path='family_name' visible sortable multisortable></eg-grid-field>
+  <eg-grid-field label="[% ('First Name') %]" path='first_given_name' visible sortable multisortable></eg-grid-field>
+  <eg-grid-field label="[% ('Middle Name') %]" path='second_given_name' visible sortable multisortable></eg-grid-field>
+  <eg-grid-field label="[% ('DoB') %]" path='dob' visible sortable multisortable></eg-grid-field>
+  <eg-grid-field label="[% ('Home Library') %]" path='home_ou.shortname' visible></eg-grid-field>
+  <eg-grid-field label="[% ('Created On') %]" path='create_date' visible sortable multisortable></eg-grid-field>
+
+  <eg-grid-field label="[% ('Mailing:Street 1') %]" path='mailing_address.street1' visible></eg-grid-field>
+  <eg-grid-field label="[% ('Mailing:Street 2') %]" path='mailing_address.street2'></eg-grid-field>
+  <eg-grid-field label="[% ('Mailing:City') %]" path='mailing_address.city'></eg-grid-field>
+  <eg-grid-field label="[% ('Mailing:County') %]" path='mailing_address.county'></eg-grid-field>
+  <eg-grid-field label="[% ('Mailing:State') %]" path='mailing_address.state'></eg-grid-field>
+  <eg-grid-field label="[% ('Mailing:Zip') %]" path='mailing_address.post_code'></eg-grid-field>
+
+  <eg-grid-field label="[% ('Billing:Street 1') %]" path='billing_address.street1'></eg-grid-field>
+  <eg-grid-field label="[% ('Billing:Street 2') %]" path='billing_address.street2'></eg-grid-field>
+  <eg-grid-field label="[% ('Billing:City') %]" path='billing_address.city'></eg-grid-field>
+  <eg-grid-field label="[% ('Billing:County') %]" path='billing_address.county'></eg-grid-field>
+  <eg-grid-field label="[% ('Billing:State') %]" path='billing_address.state'></eg-grid-field>
+  <eg-grid-field label="[% ('Billing:Zip') %]" path='billing_address.post_code'></eg-grid-field>
+</eg-grid>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_stat_cats.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_stat_cats.tt2
new file mode 100644 (file)
index 0000000..21eb217
--- /dev/null
@@ -0,0 +1,19 @@
+<div class="row pad-vert" ng-repeat="map in patron().stat_cat_entries()">
+  <div class="col-md-12 well" style="margin-left:12px">
+    <div class="row">
+      <div class="col-md-7">
+        <span class="strong-text">{{map.stat_cat().name()}}</span>
+        <span class="pad-horiz">{{map.stat_cat_entry()}}</span>
+      </div>
+      <div class="col-md-5">
+        <div class="pull-right">
+          <span class="pad-horiz alert alert-warning" 
+            ng-if="map.stat_cat().opac_visible() == 't'">[% l('Patron Visible') %]</span>
+          <span class="pad-horiz alert alert-info" 
+            ng-if="map.stat_cat().opac_visible() == 'f'">[% l('Staff Only') %]</span>
+          <span>[% l('@ [_1]', '{{map.stat_cat().owner().shortname()}}') %]</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2
new file mode 100644 (file)
index 0000000..1f09c77
--- /dev/null
@@ -0,0 +1,143 @@
+
+<div ng-cloak>
+  <div ng-show="patron()" id="patron-summary-grid">
+    <div class="row" 
+      ng-class="{'patron-summary-divider' : !$index}"
+      ng-repeat="penalty in alert_penalties()">
+      <div 
+        class="col-md-9 patron-summary-alert"
+        title="{{penalty.standing_penalty().name()}}">
+        {{penalty.note() || penalty.standing_penalty().label()}}
+      </div>
+      <div class="col-md-3">
+        {{penalty.set_date() | date:'shortDate'}}
+      </div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-divider' : alert_penalties().length}">
+      <div class="col-md-5">[% l('Profile') %]</div>
+      <div class="col-md-7">{{patron().profile().name()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Home Library') %]</div>
+      <div class="col-md-7">{{patron().home_ou().shortname()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Net Access') %]</div>
+      <div class="col-md-7">{{patron().net_access_level().name()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Last Activity') %]</div>
+      <div class="col-md-7">{{patron().usr_activity()[0].event_time() | date:'shortDate'}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Last Updated') %]</div>
+      <div class="col-md-7">{{patron().last_update_time() | date:'shortDate'}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Create Date') %]</div>
+      <div class="col-md-7">{{patron().create_date() | date:'shortDate'}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Expire Date') %]</div>
+      <div class="col-md-7">{{patron().expire_date() | date:'shortDate'}}</div>
+    </div>
+    <div class="row patron-summary-divider" 
+      ng-class="{'patron-summary-alert' : patron_stats().fines.balance_owed}">
+      <div class="col-md-5">[% l('Fines Owed') %]</div>
+      <div class="col-md-7">
+        {{patron_stats().fines.balance_owed | currency}}
+      </div>
+    </div>
+    <div class="row"
+      ng-show="patron_stats().fines.group_balance_owed > patron_stats().fines.balance_owed"
+      ng-class="{'patron-summary-alert' : patron_stats().fines.group_balance_owed}">
+      <div class="col-md-5">[% l('Group Fines') %]</div>
+      <div class="col-md-7">
+        {{patron_stats().fines.group_balance_owed | currency}}
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Items Out') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.out}}</div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-alert' : patron_stats().checkouts.overdue}">
+      <div class="col-md-5">[% l('Overdue') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.overdue}}</div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-alert' : patron_stats().checkouts.long_overdue}">
+      <div class="col-md-5">[% l('Long Overdue') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.long_overdue}}</div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-alert' : patron_stats().checkouts.claims_returned}">
+      <div class="col-md-5">[% l('Claimed Returned') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.claims_returned}}</div>
+    </div>
+    <div class="row" 
+      ng-class="{'patron-summary-alert' : patron_stats().checkouts.lost}">
+      <div class="col-md-5">[% l('Lost') %]</div>
+      <div class="col-md-7">{{patron_stats().checkouts.lost}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Holds') %]</div>
+      <div class="col-md-7">
+        {{patron_stats().holds.total}} / {{patron_stats().holds.ready}}
+      </div>
+    </div>
+    <div class="row patron-summary-divider">
+      <div class="col-md-5">[% l('Card') %]</div>
+      <div class="col-md-7">{{patron().card().barcode()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Username') %]</div>
+      <div class="col-md-7">{{patron().usrname()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Day Phone') %]</div>
+      <div class="col-md-7">{{patron().day_phone()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Evening Phone') %]</div>
+      <div class="col-md-7">{{patron().evening_phone()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Other Phone') %]</div>
+      <div class="col-md-7">{{patron().other_phone()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('ID1') %]</div>
+      <div class="col-md-7">{{patron().ident_type().name()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('ID2') %]</div>
+      <div class="col-md-7">{{patron().ident_type2().name()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-5">[% l('Email') %]</div>
+      <div class="col-md-7">{{patron().email()}}</div>
+    </div>
+    <div class="row" ng-repeat="map in summary_stat_cats()">
+      <div class="col-md-5">{{map.stat_cat().name()}}</div>
+      <div class="col-md-7">{{map.stat_cat_entry()}}</div>
+    </div>
+  </div>
+
+  <div class="row" ng-repeat="addr in patron().addresses()">
+    <div class="panel">
+      <div class="panel-body">
+        <fieldset>
+          <legend>
+            {{addr.address_type()}} 
+            <a href class="pad-horiz patron-summary-act-link" 
+              ng-click="print_address(addr)">[% l('(print)') %]</a>
+          </legend>
+          <div>{{addr.street1()}} {{addr.street2()}}</div>
+          <div>{{addr.city()}}, {{addr.state()}} {{addr.post_code()}}</div>
+        </fieldset>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_triggered_events.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_triggered_events.tt2
new file mode 100644 (file)
index 0000000..fe5091f
--- /dev/null
@@ -0,0 +1,3 @@
+<!-- insert the patron registration UI -->
+<eg-embed-frame url="triggered_events_url" handlers="funcs"></eg-embed-frame>
+
diff --git a/Open-ILS/src/templates/staff/circ/patron/t_xact_details.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_xact_details.tt2
new file mode 100644 (file)
index 0000000..7bc04e7
--- /dev/null
@@ -0,0 +1,144 @@
+<h3>[% l('Transaction #[_1]', '{{xact.id()}}') %]</h3>
+
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Billing Location') %]</div>
+  <div class="col-md-2">{{xact.billing_location().shortname()}}</div>
+  <div class="col-md-2 strong-text">[% l('Total Billed') %]</div>
+  <div class="col-md-2">{{xact.summary().total_owed() | currency}}</div>
+  <div class="col-md-2 strong-text">[% l('Title') %]</div>
+  <div class="col-md-2">
+    <a ng-if="title_id" href="[% ctx.base_path %]/opac/record/{{title_id}}">{{title}}</a>
+    <span ng-if="!title_id">{{title}}</span>
+  </div>
+</div>
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Type') %]</div>
+  <div class="col-md-2">{{xact.summary().xact_type()}}</div>
+  <div class="col-md-2 strong-text">[% l('Total Paid') %]</div>
+  <div class="col-md-2">{{xact.summary().total_paid() | currency}}</div>
+  <div class="col-md-2 strong-text">[% l('Checked Out') %]</div>
+  <div class="col-md-2">{{xact.circulation().xact_start() | date:'short'}}</div>
+</div>
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Start') %]</div>
+  <div class="col-md-2">{{xact.xact_start() | date:'short'}}</div>
+  <div class="col-md-2 strong-text">[% l('Total Billed') %]</div>
+  <div class="col-md-2">{{xact.summary().balance_owed() | currency}}</div>
+  <div class="col-md-2 strong-text">[% l('Due Date') %]</div>
+  <div class="col-md-2">{{xact.circulation().due_date() | date:'short'}}</div>
+</div>
+<div class="row">
+  <div class="col-md-2 strong-text">[% l('Finish') %]</div>
+  <div class="col-md-2">{{xact.xact_finish() | date:'short'}}</div>
+  <div class="col-md-2 strong-text">[% l('Renewal?') %]</div>
+  <div class="col-md-2">
+    <span ng-if="xact.circulation.desk_renewal == 't'">[% l('Desk') %]</span>
+    <span ng-if="xact.circulation.phone_renewal == 't'">[% l('Phone') %]</span>
+    <span ng-if="xact.circulation.opac_renewal == 't'">[% l('OPAC') %]</span>
+  </div>
+  <div class="col-md-2 strong-text">[% l('Checked In') %]</div>
+  <div class="col-md-2">{{xact.circulation().checkin_time() | date:'short'}}</div>
+</div>
+
+<div ng-if="xact.circulation()">
+  <hr/>
+  <h3>[% l('Item Summary') %]</h3>
+  <div class="row">
+    <div class="col-md-2 strong-text">[% l('Barcode') %]</div>
+    <div class="col-md-2">
+      <a title="[% l('Item Details') %]" target="_self"
+        href='./cat/item/{{xact.circulation().target_copy().id()}}'>
+        {{xact.circulation().target_copy().barcode()}}
+      </a>
+    </div>
+    <div class="col-md-2 strong-text">[% l('Location') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().location().name()}}
+    </div>
+    <div class="col-md-2 strong-text">[% l('Call Number') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().call_number().label()}}
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-md-2 strong-text">[% l('Status') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().status().name()}}
+    </div>
+    <div class="col-md-2 strong-text">[% l('Circulate') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().circulate() == 't'}}
+    </div>
+    <div class="col-md-2 strong-text">[% l('Reference') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().ref() == 't'}}
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-md-2 strong-text">[% l('Holdable') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().holdable() == 't'}}
+    </div>
+    <div class="col-md-2 strong-text">[% l('OPAC Visible') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().opac_visible() == 't'}}
+    </div>
+
+    <div class="col-md-2 strong-text">[% l('Created') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().create_date() | date:'short'}}
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-md-2 strong-text">[% l('Edited') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().edit_date() | date:'short'}}
+    </div>
+    <div class="col-md-2 strong-text">[% l('Age Protect') %]</div>
+    <div class="col-md-2">
+      {{xact.circulation().target_copy().age_protect().name()}}
+    </div>
+    <div class="col-md-2 strong-text">[% l('Total Circulations') %]</div>
+    <div class="col-md-2">
+      TODO
+    </div>
+  </div>
+</div>
+
+
+<!-- set a lower default page size (limit) to allow for more space -->
+<hr/>
+<eg-grid
+  main-label="[% l('Bills') %]"
+  idl-class="mb"
+  id-field="id"
+  grid-controls="xactGridControls"
+  auto-fields="true"
+  page-size="10">
+
+  <eg-grid-action 
+    label="[% l('Void Billings') %]" handler="voidBillings"></eg-grid-action>
+
+  <eg-grid-action 
+    label="[% l('Edit Note') %]" handler="editBillNotes"></eg-grid-action>
+
+</eg-grid>
+
+<!-- TODO: this grid may contain objects (payments) of different types.. 
+    apply manual columns, see xul -->
+<!-- NOTE: sorting disabled since payments are fetched via non-sortable API -->
+<br/>
+<eg-grid
+  main-label="[% l('Payments') %]"
+  idl-class="mp"
+  id-field="id"
+  auto-fields="true"
+  grid-controls="paymentGridControls"
+  page-size="10">
+  <eg-grid-action 
+    label="[% l('Edit Note') %]" handler="editPaymentNotes"></eg-grid-action>
+
+  <eg-grid-field path="cash_payment.cash_drawer.name" 
+    label="[% l('Cash Drawer') %]"></eg-grid-field>
+</eg-grid>
+
diff --git a/Open-ILS/src/templates/staff/circ/renew/index.tt2 b/Open-ILS/src/templates/staff/circ/renew/index.tt2
new file mode 100644 (file)
index 0000000..415556b
--- /dev/null
@@ -0,0 +1,20 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Renew"); 
+  ctx.page_app = "egRenewApp";
+%]
+
+[% BLOCK APP_JS %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/grid.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/ui.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/services/user.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
+[% INCLUDE 'staff/circ/share/circ_strings.tt2' %]
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/patron/app.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/renew/app.js"></script>
+<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ.css" />
+[% END %]
+
+<div ng-view></div>
+
+[% END %]
diff --git a/Open-ILS/src/templates/staff/circ/renew/t_renew.tt2 b/Open-ILS/src/templates/staff/circ/renew/t_renew.tt2
new file mode 100644 (file)
index 0000000..c2880c1
--- /dev/null
@@ -0,0 +1,141 @@
+<!-- item renewal form / list -->
+
+<div class="container-fluid" style="text-align:center">
+  <div class="alert alert-info alert-less-pad strong-text-2">
+    [% l('Renew Items') %]
+  </div>
+</div>
+
+<div class="row">
+  <div class="col-md-6">
+    <form ng-submit="renew(renewalArgs)" role="form" class="form-inline">
+      <div class="input-group">
+
+        <label class="input-group-addon" 
+          for="patron-renewal-barcode" >[% l('Barcode') %]</label>
+
+        <input focus-me="focusBarcode" class="form-control"
+          ng-model="renewalArgs.copy_barcode" 
+          id="patron-renewal-barcode" type="text"/> 
+
+        <input class="btn btn-default" type="submit" value="[% l('Submit') %]"/>
+      </div>
+    </form>
+  </div>
+  <div class="col-md-6">
+    <div class="flex-row">
+      <div class="flex-cell"></div>
+      <div class="checkbox pad-horiz">
+        <label>
+          <input type="checkbox" ng-model="renewalArgs.sticky_date"/>
+          [% l('Specific Due Date') %]
+        </label>
+      </div>
+      <!-- FIXME: This needs a time component as well, but type="datetime" 
+            is not yet supported by any browsers -->
+      <div><input eg-date-input class="form-control" ng-model="renewalArgs.due_date"/>
+      </div>
+    </div>
+  </div>
+</div>
+<hr/>
+
+<eg-grid
+  id-field="index"
+  features="-sort,-multisort"
+  items-provider="gridDataProvider"
+  grid-controls="gridControls"
+  persist-key="circ.renew">
+
+  <eg-grid-action 
+    handler="fetchLastCircPatron"
+    label="[% l('Retrieve Last Patron Who Circulated Item') %]">
+  </eg-grid-action>
+  <eg-grid-action 
+    handler="showLastFewCircs"
+    label="[% l('Show Last Few Circluations') %]">
+  </eg-grid-action>
+  <eg-grid-action divider="true"></eg-grid-action>
+  <eg-grid-action 
+    handler="showMarkDamaged"
+    label="[% l('Mark Items Damaged') %]">
+  </eg-grid-action>
+  <eg-grid-action divider="true"></eg-grid-action>
+  <eg-grid-action 
+    handler="abortTransit"
+    label="[% l('Abort Transits') %]">
+  </eg-grid-action>
+
+
+  <eg-grid-field label="[% l('Alert Msg') %]"   
+    path="acp.alert_message"></eg-grid-field>
+
+  <eg-grid-field label="[% l('Balance Owed') %]"     
+    path='mbts.balance_owed'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Barcode') %]" path="acp_barcode">
+    <!-- FIXME: ng-if / ng-disabled not working since the contents 
+        are $interpolate'd and not $compile'd.
+        I want to hide / disable the href when there is no acp ID 
+    -->
+    <a href="./cat/item/{{item.acp.id()}}/summary" target="_self">
+      {{item.copy_barcode}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Bill #') %]"     
+    path='circ.id'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Call Number') %]" 
+    path="acn.label"></eg-grid-field>
+
+  <eg-grid-field label="[% l('Due Date') %]"    
+    path='circ.due_date' dateformat='short'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Family Name') %]"    
+    path='au.family_name'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Location') %]" 
+    path='acp.location.name'> </eg-grid-field>
+
+  <eg-grid-field label="[% l('Remaining Renewals') %]" 
+    path='circ.renewal_remaining'></eg-grid-field>
+
+  <eg-grid-field label="[% l('Title') %]" path="title">
+    <a target="_self" href="[% ctx.base_path %]/opac/record/{{record.doc_id()}}">
+      {{item.title}}
+    </a>
+  </eg-grid-field>
+
+  <eg-grid-field label="[% l('Author') %]"      
+    path="author" hidden></eg-grid-field>
+
+  <eg-grid-field path="circ.*" parent-idl-class="circ" hidden></eg-grid-field>
+  <eg-grid-field path="acp.*" parent-idl-class="acp" hidden></eg-grid-field>
+  <eg-grid-field path="acn.*" parent-idl-class="acn" hidden></eg-grid-field>
+  <eg-grid-field path="record.*" parent-idl-class="mvr" hidden></eg-grid-field>
+  <eg-grid-field path="mbts.*" parent-idl-class="mbts" hidden></eg-grid-field>
+  <eg-grid-field path="au.*" parent-idl-class="au" hidden></eg-grid-field>
+</eg-grid>
+
+<div class="flex-row pad-vert">
+  <div class="flex-cell"></div>
+  <div class="pad-horiz">
+    <button class="btn btn-default" 
+      ng-click="print_receipt()">[% l('Print Receipt') %]</button>
+  </div>
+  <div class="checkbox">
+    <label>
+      <input ng-model="trim_list" type="checkbox"/>
+      [% l('Trim List (20 Rows)') %]
+    </label>
+  </div>
+  <div class="pad-horiz"></div>
+  <div class="checkbox">
+    <label>
+      <input ng-model="strict_barcode" type="checkbox"/>
+      [% l('Strict Barcode') %]
+    </label>
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/circ/share/circ_strings.tt2 b/Open-ILS/src/templates/staff/circ/share/circ_strings.tt2
new file mode 100644 (file)
index 0000000..316e64a
--- /dev/null
@@ -0,0 +1,39 @@
+[%# Strings for circ/services/circ.js %]
+
+<script>
+angular.module('egCoreMod').run(['egStrings', function(s) {
+s.PATRON_CARD_INACTIVE =
+  "[% l('The card used to retrieve this account is inactive and may not be used to circulate items.') %]";
+s.PATRON_INACTIVE =
+  "[% l('This account is inactive and may not circulate items.') %]";
+s.PATRON_ACCOUNT_EXPIRED =
+  "[% l('This account has expired and may not circulate items.') %]";
+s.CIRC_CLAIMS_RETURNED = 
+  '[% l('Item "[_1]" is marked as Claims Returned', '{{barcode}}') %]';
+s.CHECKOUT_FAILED_GENERIC =
+  '[% l('Unable to checkout copy "[_1]" : [_2]', '{{barcode}}', '{{textcode}}') %]';
+s.COPY_ALERT_MSG_DIALOG_TITLE =
+  '[% l('Copy Alert Message for "[_1]"', '{{copy_barcode}}') %]';
+s.UNCAT_ALERT_DIALOG =
+  '[% l('Copy "[_1]" was mis-scanned or is not cataloged', '{{copy_barcode}}') %]';
+s.PERMISSION_DENIED = 
+  '[% l('Permission Denied : [_1]', '{{permission}}') %]';
+s.PRECAT_CHECKIN_MSG = 
+  '[% l("This item needs to be routed to CATALOGING") %]';
+s.LOCATION_ALERT_MSG =
+  '[% l("Item [_1] needs to be routed to [_2]", 
+    "{{copy.barcode()}}","{{copy.location().name()}}") %]';
+s.MARK_DAMAGED_CONFIRM = '[% l("Mark {{num_items}} items as DAMAGED?") %]';
+s.MARK_MISSING_CONFIRM = '[% l("Mark {{num_items}} items as MISSING?") %]';
+s.ABORT_TRANSIT_CONFIRM = '[% l("Abort {{num_transits}} transits?") %]';
+s.ROUTE_TO_HOLDS_SHELF = '[% l("Holds Shelf") %]';
+s.ROUTE_TO_CATALOGING = '[% l("Cataloging") %]';
+s.COPY_IN_TRANSIT = '[% l("Copy is In-Transit") %]';
+s.TOO_MANY_CLAIMS_RETURNED = 
+  '[% l("Patron exceeds claims returned count.  Force this action?") %]';
+s.MARK_NEVER_CHECKED_OUT = 
+  '[% l("Mark Never Checked Out: [_1]", "{{barcodes.toString()}}") %]'
+}]);
+</script>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/hold_strings.tt2 b/Open-ILS/src/templates/staff/circ/share/hold_strings.tt2
new file mode 100644 (file)
index 0000000..9e67e19
--- /dev/null
@@ -0,0 +1,30 @@
+[%# Strings for circ/services/circ.js %]
+
+<script>
+angular.module('egCoreMod').run(['egStrings', function(s) {
+s['HOLD_STATUS_-1'] = "[% l('Error (-1)') %]";
+s.HOLD_STATUS_1 = "[% l('Waiting for Copy') %]";
+s.HOLD_STATUS_2 = "[% l('Waiting for Capture') %]";
+s.HOLD_STATUS_3 = "[% l('In Transit') %]";
+s.HOLD_STATUS_4 = "[% l('Ready for Pickup') %]";
+s.HOLD_STATUS_5 = "[% l('Hold Shelf Delay') %]";
+s.HOLD_STATUS_6 = "[% l('Canceled') %]";
+s.HOLD_STATUS_7 = "[% l('Suspended') %]";
+s.HOLD_STATUS_8 = "[% l('Wrong Shelf') %]";
+s.ACTIVATE_HOLDS = "[% l('Activate [_1] Hold(s)?', '{{num_holds}}') %]"
+s.SUSPEND_HOLDS = "[% l('Suspend [_1] Hold(s)?', '{{num_holds}}') %]"
+s.SET_TOP_OF_QUEUE = 
+  "[% l('Move [_1] Hold(s) to the front of the holds queue above other holds that are not likewise flagged as Top of Queue?', 
+    '{{num_holds}}') %]";
+s.CLEAR_TOP_OF_QUEUE = 
+  "[% l('Unset the Top of Queue flag for [_1] Hold(s)?', '{{num_holds}}') %]";
+s.TRANSFER_HOLD_TO_TITLE = 
+  "[% l('Tranfer [_1] Hold(s) to bib record ID [_2]?', '{{num_holds}}', '{{bib_id}}') %]";
+s.NO_HOLD_TRANSFER_TITLE_MARKED = 
+  "[% l('No record is marked as a hold transfer target!') %]";
+s.RETARGET_HOLDS = 
+  "[% l('Reset hold(s) [_1]?', '{{hold_ids}}') %]";
+}]);
+</script>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_backdate_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_backdate_dialog.tt2
new file mode 100644 (file)
index 0000000..034e909
--- /dev/null
@@ -0,0 +1,24 @@
+<div class="modal-header">
+  <button type="button" class="close" 
+    ng-click="cancel()" aria-hidden="true">&times;</button>
+  <h4 class="modal-title">
+    [% l('Backdate Already Checked-In Circulations') %]
+  </h4>
+</div>
+<div class="modal-body">
+  <div>[% l('Number of circulations selected: [_1]', '{{dialog.num_circs}}') %]</div>
+  <div class="pad-vert">
+    <progress max="dialog.num_circs" value="dialog.num_processed"></progress>
+  </div>
+  <div class="pad-vert row">
+    <div class="col-md-6">[% l('Effective Date:') %]</div>
+    <div class="col-md-6">
+      <input eg-date-input required 
+        class="form-control" ng-model="dialog.backdate"/>
+    </div>
+  </div>
+</div>
+<div class="modal-footer">
+  <button class="btn btn-primary" ng-click="ok()">[% l('Submit') %]</button>
+  <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_bad_barcode_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_bad_barcode_dialog.tt2
new file mode 100644 (file)
index 0000000..c304416
--- /dev/null
@@ -0,0 +1,23 @@
+<div>
+  <div class="modal-header">
+    <button type="button" class="close" ng-click="cancel()" 
+      aria-hidden="true">&times;</button>
+    <h4 class="modal-title">[% l('Bad Barcode') %]</h4>
+  </div>
+  <div class="modal-body">
+    <img src="[% ctx.media_prefix %]/images/bad_barcode.png"/>
+    <div>
+[% |l('{{barcode}}') %]
+Bad check digit, possibly due to a bad scan.  Use this barcode ("[_1]") anyway?
+[% END %]
+    </div>
+  </div>
+  <div class="modal-footer">
+    <input type="submit" class="btn btn-primary" 
+      ng-click="ok()" value="[% l('Accept Barcode') %]"/>
+    <button class="btn btn-warning" 
+      ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_bill_patron_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_bill_patron_dialog.tt2
new file mode 100644 (file)
index 0000000..b946b8c
--- /dev/null
@@ -0,0 +1,93 @@
+<!-- edit bucket dialog -->
+<form ng-submit="ok(billArgs)" role="form" class="form-horizontal">
+  <div class="modal-content">
+    <div class="modal-header">
+      <button type="button" class="close" 
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">
+        [% l('Bill Patron: [_1], [_2] [_3] : [_4]',
+            '{{patron.family_name()}}',
+            '{{patron.first_given_name()}}',
+            '{{patron.second_given_name()}}',
+            '{{patron.card().barcode()}}') %]
+      </h4>
+
+      <div ng-if="xact">
+        <hr/>
+        <div class="row">
+          <div class="col-md-3">[% l('Bill #') %]</div>
+          <div class="col-md-3">{{xact.id}}</div>
+          <div class="col-md-3">[% l('Total Billed') %]</div>
+          <div class="col-md-3">{{xact.summary.total_owed | currency}}</div>
+        </div>
+        <div class="row">
+          <div class="col-md-3">[% l('Type') %]</div>
+          <div class="col-md-3">{{xact.summary.xact_type}}</div>
+          <div class="col-md-3">[% l('Total Paid') %]</div>
+          <div class="col-md-3">{{xact.summary.total_paid | currency}}</div>
+        </div>
+        <div class="row">
+          <div class="col-md-3">[% l('Start') %]</div>
+          <div class="col-md-3">{{xact.xact_start | date:'short'}}</div>
+          <div class="col-md-3">[% l('Total Billed') %]</div>
+          <div class="col-md-3">{{xact.summary.balance_owed | currency}}</div>
+        </div>
+        <div class="row">
+          <div class="col-md-3">[% l('Finish') %]</div>
+          <div class="col-md-3">{{xact.xact_finish | date:'short'}}</div>
+          <div class="col-md-3">[% l('Renewal?') %]</div>
+          <div class="col-md-3">
+            <span ng-if="xact.circulation.desk_renewal == 't'">[% l('Desk') %]</span>
+            <span ng-if="xact.circulation.phone_renewal == 't'">[% l('Phone') %]</span>
+            <span ng-if="xact.circulation.opac_renewal == 't'">[% l('OPAC') %]</span>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="modal-body">
+      <div class="form-group">
+        <label for="bill-dialog-location" class="control-label col-md-4">
+          [% l('Location:') %]
+        </label>
+        <div class="col-md-8">
+          <p class="form-control-static">{{location.shortname()}}</p>
+        </div>
+      </div>
+
+      <div class="form-group">
+        <label for="bill-dialog-type" class="control-label col-md-4">
+          [% l('Billing Type:') %]
+        </label>
+        <div class="col-md-8">
+          <select ng-model="billArgs.billingType" class="form-control"
+            ng-change="updateDefaultPrice()">
+            <option ng-repeat="type in billingTypes" value="{{type.id()}}">
+              {{type.name()}}
+            </option>
+          </select>
+        </div>
+      </div>
+      <div class="form-group">
+        <label for="bill-dialog-amount" class="control-label col-md-4">[% l('Amount:') %]</label>
+        <div class="col-md-8">
+          <input type="number" min="0" step="any" class="form-control" 
+            focus-me='focus' required id="bill-dialog-amount" 
+            ng-model="billArgs.amount"/>
+        </div>
+      </div>
+      <div class="form-group">
+        <label for="bill-dialog-note" class="control-label col-md-4">[% l('Note:') %]</label>
+        <div class="col-md-8">
+          <textarea rows="3" class="form-control" placeholder="[% l('Note...') %]"
+            id="bill-dialog-note" ng-model="billArgs.note"></textarea>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-success" value="[% l('Submit Bill') %]"/>
+      <button class="btn btn-warning" ng-click="cancel($event)">[% l('Cancel') %]</button>
+    </div>
+  </div>
+</form>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_cancel_hold_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_cancel_hold_dialog.tt2
new file mode 100644 (file)
index 0000000..81417f2
--- /dev/null
@@ -0,0 +1,38 @@
+<form ng-submit="ok()" role="form" class="form-horizontal">
+  <div class="modal-content">
+    <div class="modal-header">
+      <button type="button" class="close" 
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">
+        [% l('Cancel [_1] Hold(s)', '{{args.num_holds}}') %]
+      </h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group">
+        <label for="hold-cancel-reason" class="control-label col-md-4">
+          [% l('Cancel Reason:') %]
+        </label>
+        <div class="col-md-8">
+          <select class="form-control" id="hold-cancel-reason"
+            ng-model="args.cancel_reason"
+            ng-options="reason.label() for reason in args.cancel_reasons">
+          </select>
+        </div>
+      </div>
+      <div class="form-group">
+        <label for="hold-cancel-note" class="control-label col-md-4">
+          [% l('Note:') %]
+        </label>
+        <div class="col-md-8">
+          <textarea rows="3" class="form-control" placeholder="[% l('Note...') %]"
+            id="hold-cancel-note" ng-model="args.note"></textarea>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-success" value="[% l('Cancel Hold') %]"/>
+      <button class="btn btn-warning" ng-click="cancel($event)">[% l('Exit') %]</button>
+    </div>
+  </div>
+</div>
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_circ_exists_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_circ_exists_dialog.tt2
new file mode 100644 (file)
index 0000000..3a8b5d1
--- /dev/null
@@ -0,0 +1,31 @@
+<form class="form-validated" novalidate ng-submit="ok()" name="form">
+  <div>
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" 
+          ng-click="cancel()" aria-hidden="true">&times;</button>
+        <h4 class="modal-title">[% l('Open Circulation') %]</h4>
+      </div>
+      <div class="modal-body">
+        <div ng-if="sameUser">
+          [% |l("{{circDate | date:'shortDate'}}") %]
+          There is an open circulation on the requested item.  
+          This item was already checked out to this user on [_1].
+          [% END %]
+        </div>
+        <div ng-if="!sameUser">
+          [% |l("{{circDate | date:'shortDate'}}") %]
+          There is an open circulation on the requested item.  
+          This copy was checked out by another patron on [_1].
+          [% END %]
+        </div>
+      </div>
+      <div class="modal-footer">
+        <input type="submit" class="btn btn-primary" 
+            value="[% l('Normal Checkin then Checkout') %]"/>
+        <button class="btn btn-warning" 
+            ng-click="cancel($event)">[% l('Cancel') %]</button>
+      </div>
+    </div> <!-- modal-content -->
+  </div> <!-- modal-dialog -->
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_copy_in_transit_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_copy_in_transit_dialog.tt2
new file mode 100644 (file)
index 0000000..4d38922
--- /dev/null
@@ -0,0 +1,32 @@
+<div>
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">[% l('Copy In Transit') %]</h4>
+  </div>
+  <div class="modal-body">
+    <div class="strong-text">
+      [% l('There is an open transit on copy [_1]', 
+        '{{transit.target_copy().barcode()}}') %]
+    </div>
+    <div class="pad-vert"></div>
+    <div class="row">
+      <div class="col-md-4">[% l('Transit Date:') %]</div>
+      <div class="col-md-8">{{transit.source_send_time() | date:'short'}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Transit Source:') %]</div>
+      <div class="col-md-8">{{transit.source().shortname()}}</div>
+    </div>
+    <div class="row">
+      <div class="col-md-4">[% l('Transit Destination:') %]</div>
+      <div class="col-md-8">{{transit.dest().shortname()}}</div>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <input type="submit" class="btn btn-primary" ng-click="ok()"
+        value="[% l('Abort Transit then Checkout') %]"/>
+    <button class="btn btn-warning" 
+        ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_copy_not_avail_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_copy_not_avail_dialog.tt2
new file mode 100644 (file)
index 0000000..711e777
--- /dev/null
@@ -0,0 +1,20 @@
+<div>
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Copy Not Available.') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="alert alert-warning">
+      [% l('Copy Status: [_1]', '{{copyStatus.name()}}') %]
+    </div>
+  </div>
+  <div class="modal-footer">
+    <input type="submit" class="btn btn-primary" ng-click="ok()"
+        value="[% l('Force this action?') %]"/>
+    <button class="btn btn-warning" 
+      ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_event_override_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_event_override_dialog.tt2
new file mode 100644 (file)
index 0000000..5850ac5
--- /dev/null
@@ -0,0 +1,27 @@
+<form ng-submit="ok()" role="form">
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Exceptions occurred during checkout.') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="panel panel-danger">
+      <div class="panel-heading">{{evt.textcode}}</div>
+      <div class="panel-body">
+        <div ng-if="copy_barcode" class="strong-text-2">{{copy_barcode}}</div>
+        {{evt.desc}}
+      </div>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <i ng-if="auto_override">[% |l %]If overridden, subsequent checkouts during this patron's 
+ session will auto-override this event[% END %]</i>
+    <br/><br/>
+    <input type="submit" class="btn btn-primary" 
+        value="[% l('Force Action?') %]"/>
+    <button class="btn btn-warning" 
+      ng-click="cancel($event)">[% l('Cancel') %]</button>
+  </div>
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_copy_quality_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_copy_quality_dialog.tt2
new file mode 100644 (file)
index 0000000..19aa885
--- /dev/null
@@ -0,0 +1,24 @@
+<div class="modal-content">
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Accept only "Good Quality" copies?') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="form-group">
+      <div class="col-md-4">
+        <button class="btn btn-default" ng-click="good()">[% l('Good Condition') %]</button>
+      </div>
+      <div class="col-md-4">
+        <button class="btn btn-default" ng-click="any()">[% l('Any Condition') %]</button>
+      </div>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_dates.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_dates.tt2
new file mode 100644 (file)
index 0000000..b145d0e
--- /dev/null
@@ -0,0 +1,75 @@
+<div class="modal-content" id='hold-notify-settings'>
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Modify Dates for [_1] Hold(s)', '{{num_holds}}') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="row header-row">
+      <div class="col-md-12">
+        [% l('Check the checkbox next to each field you wish to modify.') %]
+      </div>
+    </div>
+    <hr/>
+    <div class="row">
+      <div class="col-md-1">
+        <label for="modify_thaw_date" class="sr-only">[% l('Update Activate Email') %]</label>
+        <input id='modify_thaw_date' ng-model="args.modify_thaw_date" type="checkbox"/>
+      </div>
+      <div class="col-md-4">
+        <label for='thaw_date'>[% l("Hold Activate Date") %]</label>
+      </div>
+      <div class="col-md-7">
+        <input id='thaw_date' eg-date-input 
+          ng-disabled="!args.modify_thaw_date" ng-model="args.thaw_date"/>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-1">
+        <label for="modify_request_time" class="sr-only">[% l('Update Phone Number') %]</label>
+        <input id='modify_request_time' ng-model="args.modify_request_time" type="checkbox"/>
+      </div>
+      <div class="col-md-4">
+        <label for='request_time'>[% l("Hold Request Date") %]</label>
+      </div>
+      <div class="col-md-7">
+        <input id='request_time' eg-date-input 
+          ng-disabled="!args.modify_request_time" ng-model="args.request_time"/>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-1">
+        <label for="modify_expire_time" class="sr-only">[% l('Update Expire Time') %]</label>
+        <input id='modify_expire_time' ng-model="args.modify_expire_time" type="checkbox"/>
+      </div>
+      <div class="col-md-4">
+        <label for='expire_time'>[% l("Hold Expire Date") %]</label>
+      </div>
+      <div class="col-md-7">
+        <input id='expire_time' eg-date-input 
+          ng-disabled="!args.modify_expire_time" ng-model="args.expire_time"/>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-1">
+        <label for="modify_shelf_expire_time" class="sr-only">[% l('Update SMS Carrier') %]</label>
+        <input id='modify_shelf_expire_time' ng-model="args.modify_shelf_expire_time" type="checkbox"/>
+      </div>
+      <div class="col-md-4">
+        <label for='shelf_expire_time'>[% l("Shelf Expire Date") %]</label>
+      </div>
+      <div class="col-md-7">
+        <input id='shelf_expire_time' eg-date-input 
+          ng-disabled="!args.modify_shelf_expire_time" ng-model="args.shelf_expire_time"/>
+      </div>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-default" ng-click="ok()">[% l('Submit') %]</button>
+    <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_details.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_details.tt2
new file mode 100644 (file)
index 0000000..1117ae1
--- /dev/null
@@ -0,0 +1,149 @@
+<!-- hold info -->
+<h4 class="pad-vert">[% l('Hold Details') %]</h4>
+<div class="flex-row">
+  <div class="flex-cell">[% l('Request Date') %]</div>
+  <div class="flex-cell well">{{hold.request_time() | date:'short'}}</div>
+  <div class="flex-cell">[% l('Capture Date') %]</div>
+  <div class="flex-cell well">{{hold.capture_time() | date:'short'}}</div>
+  <div class="flex-cell">[% l('Available On') %]</div>
+  <div class="flex-cell well">{{hold.shelf_time() | date:'short'}}</div>
+ </div>
+<div class="flex-row">
+  <div class="flex-cell">[% l('Hold Type') %]</div>
+  <div class="flex-cell well">{{hold.hold_type()}}</div>
+  <div class="flex-cell">[% l('Current Copy') %]</div>
+  <div class="flex-cell well">
+    <a href="./cat/item/{{hold.current_copy().id()}}" target="_self">
+      {{hold.current_copy().barcode()}}
+    </a>
+  </div>
+  <div class="flex-cell">[% l('Call Number') %]</div>
+  <div class="flex-cell well">{{volume.label()}}</div>
+</div>
+<div class="flex-row">
+  <div class="flex-cell">[% l('Pickup Lib') %]</div>
+  <div class="flex-cell well">{{hold.pickup_lib().shortname()}}</div>
+  <div class="flex-cell">[% l('Status') %]</div>
+  <div class="flex-cell well">{{status_string}}</div>
+  <div class="flex-cell">[% l('Behind Desk') %]</div>
+  <div class="flex-cell well">{{hold.behind_desk() == 't'}}</div>
+</div>
+<div class="flex-row">
+  <div class="flex-cell">[% l('Current Shelf Lib') %]</div>
+  <div class="flex-cell well">{{hold.current_shelf_lib().shortname()}}</div>
+  <div class="flex-cell">[% l('Current Copy Location') %]</div>
+  <div class="flex-cell well">{{copy.location().name()}}</div>
+  <div class="flex-cell">[% l('Force Copy Quality') %]</div>
+  <div class="flex-cell well">{{hold.mint_condition() == 't'}}</div>
+</div>
+<div class="flex-row">
+  <div class="flex-cell">[% l('Email Notify') %]</div>
+  <div class="flex-cell well">{{hold.email_notify() == 't'}}</div>
+  <div class="flex-cell">[% l('Phone Notify') %]</div>
+  <div class="flex-cell well">{{hold.phone_notify()}}</div>
+  <div class="flex-cell">[% l('SMS Notify') %]</div>
+  <div class="flex-cell well">{{hold.sms_notify()}}</div>
+</div>
+<div class="flex-row">
+  <div class="flex-cell">[% l('Cancel Cause') %]</div>
+  <div class="flex-cell well">{{hold.cancel_cause().label()}}</div>
+  <div class="flex-cell">[% l('Cancel Time') %]</div>
+  <div class="flex-cell well">{{hold.cancel_time() | date:'short'}}</div>
+  <div class="flex-cell">[% l('Cancel Note') %]</div>
+  <div class="flex-cell well">{{hold.cancel_note()}}</div>
+</div>
+
+<ul class="nav nav-tabs pad-vert" ng-init="detail_tab='notes'">
+  <li ng-class="{active : detail_tab == 'notes'}">
+    <a href ng-click="detail_tab = 'notes'">[% l('Notes') %]</a>
+  </li>
+  <li ng-class="{active : detail_tab == 'notify'}">
+    <a href ng-click="show_notify_tab()">
+      [% l('Staff Notifications') %]
+    </a>
+  </li>
+</ul>
+<div class="tab-content">
+  <div class="tab-pane active">
+
+    <div ng-if="detail_tab == 'notes'">
+      
+      <button class="btn btn-default" ng-click="new_note()">
+        [% l('New Note') %]
+      </button>
+
+      <div class="row pad-vert" ng-repeat="note in hold.notes()">
+        <div class="col-md-12">
+          <div class="row">
+            <div class="col-md-6 strong-text">{{note.title()}}</div>
+            <div class="col-md-6">
+              <div class="pull-right">
+                <span class="pad-horiz alert alert-info" 
+                  ng-if="note.slip() == 't'">[% l('Print on Slip') %]</span>
+                <span class="pad-horiz alert alert-warning" 
+                  ng-if="note.pub() == 't'">[% l('Patron Visible') %]</span>
+                <span class="pad-horiz alert alert-info" 
+                  ng-if="note.pub() == 'f'">[% l('Staff Only') %]</span>
+                <span class="pad-horiz alert alert-info" 
+                  ng-if="note.staff() == 't'">[% l('Staff Created') %]</span>
+                <span class="pad-horiz alert alert-info" 
+                  ng-if="note.staff() == 'f'">[% l('Patron Created') %]</span>
+              </div>
+            </div>
+          </div>
+          <div class="row">
+            <!-- hmm, not sure why the margin-left is needed.. the well? -->
+            <div class="col-md-12 well" style="margin-left:12px">
+              <div class="row">
+                <div class="col-md-8">
+                  <div class="">{{note.body()}}</div>
+                </div>
+                <div class="col-md-4">
+                  <div class="pull-right">
+                    <button ng-click="delete_note(note)" class="btn btn-warning">
+                      [% l('Delete') %]
+                    </button>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div><!-- notes tab content -->
+
+    <div ng-if="detail_tab == 'notify'">
+      
+      <button class="btn btn-default" ng-click="new_notification()">
+        [% l('Add Record of Notification') %]
+      </button>
+
+      <div class="row pad-vert" 
+          ng-repeat="notify in hold.notifications()">
+        <div class="col-md-12">
+          <div class="row">
+            <div class="col-md-6 strong-text">{{notify.method()}}</div>
+            <div class="col-md-6">
+              <div class="pull-right">
+                <span class="pad-horiz">{{notify.notify_time() | date:'short'}}</span>
+                <span>[% l('Created by [_1]', '{{notify.notify_staff().usrname()}}') %]</span>
+              </div>
+            </div>
+          </div>
+          <div class="row">
+            <!-- hmm, not sure why the margin-left is needed.. the well? -->
+            <div class="col-md-12 well" style="margin-left:12px">
+              <div class="row">
+                <div class="col-md-8">
+                  <div class="">{{notify.note()}}</div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div><!-- notes tab content -->
+
+  </div><!-- tab pane -->
+</div><!-- tab-content -->
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_edit_pickup_lib.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_edit_pickup_lib.tt2
new file mode 100644 (file)
index 0000000..895cda0
--- /dev/null
@@ -0,0 +1,23 @@
+<div class="modal-content">
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Edit hold pickup library') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="form-group">
+      <div class="col-md-4">[% l('Select Library:') %]</div>
+      <div class="col-md-8">
+        <eg-org-selector selected="args.org_unit"></eg-org-selector>
+      </div>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-default" ng-click="ok()">[% l('Submit') %]</button>
+    <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_note_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_note_dialog.tt2
new file mode 100644 (file)
index 0000000..92113da
--- /dev/null
@@ -0,0 +1,51 @@
+<form ng-submit="ok(args)" role="form">
+    <div class="modal-header">
+      <button type="button" class="close" ng-click="cancel()" 
+        aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Create a new note') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-pub">[% l('Patron Visible?') %]</label>
+        </div>
+        <div class="col-md-9">
+          <input type="checkbox" class="checkbox" 
+            id="note-pub" ng-model="args.pub"/>
+        </div>
+      </div>
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-slip">[% l('Print on Slip?') %]</label>
+        </div>
+        <div class="col-md-9">
+          <input type="checkbox" class="checkbox" 
+            id="note-slip" ng-model="args.slip"/>
+        </div>
+      </div>
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-title">[% l('Title') %]</label>
+        </div>
+        <div class="col-md-9">
+          <input type="text" class="form-control" focus-me='focusNote' required
+            id="note-title" ng-model="args.title" placeholder="[% l('Title...') %]"/>
+        </div>
+      </div>
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-body">[% l('Note Body') %]</label>
+        </div>
+        <div class="col-md-9">
+          <textarea class="form-control" required
+            id="note-body" ng-model="args.body" placeholder="[% l('Note Body...') %]">
+          </textarea>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-primary" value="[% l('OK') %]"/>
+      <button class="btn btn-warning" ng-click="cancel($event)">[% l('Cancel') %]</button>
+    </div>
+  </div> <!-- modal-content -->
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_notification_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_notification_dialog.tt2
new file mode 100644 (file)
index 0000000..01b5b48
--- /dev/null
@@ -0,0 +1,33 @@
+<form ng-submit="ok(args)" role="form">
+    <div class="modal-header">
+      <button type="button" class="close" ng-click="cancel()" 
+        aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Create Record of Hold Notification') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-method">[% l('Notification Method') %]</label>
+        </div>
+        <div class="col-md-9">
+          <input type="text" class="form-control" focus-me='focusNote' required
+            id="note-method" ng-model="args.method" placeholder="[% l('Notification Method...') %]"/>
+        </div>
+      </div>
+      <div class="form-group row">
+        <div class="col-md-3">
+          <label for="note-note">[% l('Note') %]</label>
+        </div>
+        <div class="col-md-9">
+          <textarea class="form-control" required
+            id="note-note" ng-model="args.note" placeholder="[% l('Note') %]">
+          </textarea>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-primary" value="[% l('OK') %]"/>
+      <button class="btn btn-warning" ng-click="cancel($event)">[% l('Cancel') %]</button>
+    </div>
+  </div> <!-- modal-content -->
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_notification_prefs.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_notification_prefs.tt2
new file mode 100644 (file)
index 0000000..7f2659d
--- /dev/null
@@ -0,0 +1,78 @@
+<div class="modal-content" id='hold-notify-settings'>
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Edit Notification Settings for [_1] Hold(s)', '{{num_holds}}') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="row header-row">
+      <div class="col-md-12">
+        [% l('Check the checkbox next to each field you wish to modify.') %]
+      </div>
+    </div>
+    <hr/>
+    <div class="row">
+      <div class="col-md-1">
+        <label for="activate-use-email" class="sr-only">[% l('Update Activate Email') %]</label>
+        <input id='activate-use-email' ng-model="args.update_email_notify" type="checkbox"/>
+      </div>
+      <div class="col-md-4">
+        <label for='use-email'>[% l("Send Emails") %]</label>
+      </div>
+      <div class="col-md-7">
+        <input id='use-email' ng-model="args.email_notify" 
+          type="checkbox" ng-disabled="!args.update_email_notify"/>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-1">
+        <label for="activate-phone-number" class="sr-only">[% l('Update Phone Number') %]</label>
+        <input id='activate-phone-number' ng-model="args.update_phone_notify" type="checkbox"/>
+      </div>
+      <div class="col-md-4">
+        <label for='phone-number'>[% l("Phone #") %]</label>
+      </div>
+      <div class="col-md-7">
+        <input id="phone-number" type='tel' 
+          ng-model="args.phone_notify" ng-disabled="!args.update_phone_notify"/>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-1">
+        <label for="activate-sms-number" class="sr-only">[% l('Update SMS Number') %]</label>
+        <input id='activate-sms-number' ng-model="args.update_sms_notify" type="checkbox"/>
+      </div>
+      <div class="col-md-4">
+        <label for='sms-number'>[% l("Text/SMS #") %]</label>
+      </div>
+      <div class="col-md-7">
+        <input id="sms-number" type='tel' 
+          ng-model="args.sms_notify" ng-disabled="!args.update_sms_notify"/>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-md-1">
+        <label for="activate-sms-carrier" class="sr-only">[% l('Update SMS Carrier') %]</label>
+        <input id='activate-sms-carrier' ng-model="args.update_sms_carrier" type="checkbox"/>
+      </div>
+      <div class="col-md-4">
+        <label for='sms-carrier'>[% l("SMS Carrier") %]</label>
+      </div>
+      <div class="col-md-7">
+        <select id='sms-carrier'
+          ng-model="args.sms_carrier" 
+          ng-disabled="!args.update_sms_carrier"
+          ng-options="carrier.name() for carrier in sms_carriers">
+        </select>
+      </div>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-default" ng-click="ok()">[% l('Submit') %]</button>
+    <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/circ/share/t_hold_shelf_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_hold_shelf_dialog.tt2
new file mode 100644 (file)
index 0000000..22e74e1
--- /dev/null
@@ -0,0 +1,63 @@
+<div class="">
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="ok()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">[% l('Hold Slip') %]</h4>
+  </div>
+  <div class="modal-body">
+    <div ng-switch on="hold.behind_desk">
+      <div ng-switch-when="t">
+        [% l('This item should be routed to the [_1]Private Holds Shelf[_2]',
+          '<strong>','</strong>') %]
+      </div>
+      <div ng-switch-when="f">
+        [% l('This item should be routed to the [_1]Public Holds Shelf[_2]',
+          '<strong>','</strong>') %]
+      </div>
+    </div>
+    <br/>
+    <div>
+      <span>[% l('Item Barcode:') %]</span>
+      <span>{{copy.barcode}}</span>
+    </div>
+    <div>
+      <span>[% l('Title:') %]</span>
+      <span>{{title}}</span>
+    </div>
+    <div>
+      <span>[% l('Author:') %]</span>
+      <span>{{author}}</span>
+    </div>
+    <br/>
+    <div>
+    
+    <div ng-show="patron.alias">
+      [% l('Hold for patron {{patron.alias}}') %]
+    </div>
+    <div ng-hide="patron.alias">
+      [% |l %]
+      Hold for patron {{patron.family_name}}, 
+      {{patron.first_given_name}} {{patron.second_given_name}}
+      [% END %]
+    </div>
+    <div>
+      <span>[% l('Patron Barcode:') %]</span>
+      <span>{{patron.card.barcode}}</span>
+    </div>
+    <br/>
+    <div>
+      <span>[% l('Request Date:') %]</span>
+      <span>{{hold.request_time | date:'shortDate'}}</span>
+    </div>
+    <div>
+      <span>[% l('Slip Date:') %]</span>
+      <span>{{today | date:'shortDate'}}</span>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <input type="button" class="btn btn-primary"
+      ng-click="print()" value="[% l('Print') %]"/>
+    <input type="submit" class="btn btn-warning"
+      ng-click="ok()" value="[% l('Do Not Print') %]"/>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_mark_claims_returned_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_mark_claims_returned_dialog.tt2
new file mode 100644 (file)
index 0000000..858e242
--- /dev/null
@@ -0,0 +1,25 @@
+<div class="modal-header">
+  <button type="button" class="close" 
+    ng-click="cancel()" aria-hidden="true">&times;</button>
+  <h4 class="modal-title">
+    [% l('Mark Item(s) Claims Returned') %]
+  </h4>
+</div>
+<div class="modal-body">
+  <div class="pad-vert row">
+    <div class="col-md-12">
+      [% l('Enter claims returned date for items: [_1]', 
+        '{{args.barcodes.toString()}}') %]
+    </div>
+  </div>
+  <div class="pad-vert row">
+    <div class="col-md-5">
+      <input eg-date-input required 
+        class="form-control" ng-model="args.date"/>
+    </div>
+  </div>
+</div>
+<div class="modal-footer">
+  <button class="btn btn-primary" ng-click="ok()">[% l('Submit') %]</button>
+  <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+</div>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_new_message_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_new_message_dialog.tt2
new file mode 100644 (file)
index 0000000..1cd94f0
--- /dev/null
@@ -0,0 +1,45 @@
+<form ng-submit="ok(args)" role="form">
+    <div class="modal-header">
+      <button type="button" class="close" ng-click="cancel()" 
+        aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Apply Standing Penalty / Message') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="row">
+        <div class="col-md-8">
+          <ul class="nav nav-pills">
+            <!-- 21 == SILENT_NOTE -->
+            <li ng-class="{active : args.penalty == 21}">
+              <a href ng-click="args.penalty=21">[% l('Note') %]</a>
+            </li>
+            <!-- 20 == ALERT_NOTE -->
+            <li ng-class="{active : args.penalty == 20}">
+              <a href ng-click="args.penalty=20">[% l('Alert') %]</a>
+            </li>
+            <!-- 25 == STAFF_CHR -->
+            <li ng-class="{active : args.penalty == 25}">
+              <a href ng-click="args.penalty=25">[% l('Block') %]</a>
+            </li>
+          </ul>
+        </div>
+        <div class="col-md-4 pull-right">
+          <select class="form-control" ng-model="args.penalty">
+            <option ng-selected="args.penalty < 100"></option>
+            <option ng-repeat="penalty in penalties" 
+              value="{{penalty.id()}}">{{penalty.label()}}</option>
+          </select>
+        </div>
+      </div>
+      <div class="form-group row pad-vert">
+        <div class="col-md-12">
+          <textarea class="form-control" 
+            ng-model="args.note" placeholder="[% l('Note...') %]">
+          </textarea>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" class="btn btn-primary" value="[% l('OK') %]"/>
+      <button class="btn btn-warning" ng-click="cancel($event)">[% l('Cancel') %]</button>
+    </div>
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_noncat_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_noncat_dialog.tt2
new file mode 100644 (file)
index 0000000..345848e
--- /dev/null
@@ -0,0 +1,25 @@
+<!-- edit bucket dialog -->
+<form ng-submit="ok(count)" role="form">
+  <div class="modal-header">
+    <button type="button" class="close" 
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">
+      [% l('Enter the number of {{type.name()}} circulating') %]
+    </h4>
+  </div>
+  <div class="modal-body">
+    <div class="form-group">
+      <label for="noncat-count" class="sr-only">[% l('Count') %]</label>
+      <input type="number" class="form-control" focus-me='focusMe' 
+        required id="noncat-title" ng-model="count" 
+        min="1" max="{{noncatMax}}"
+        placeholder="[% l('Count...') %]"/>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <input type="submit" class="btn btn-primary" 
+        ng-disabled="form.$invalid" value="[% l('OK') %]"/>
+    <button class="btn btn-warning" 
+      ng-click="cancel($event)">[% l('Cancel') %]</button>
+  </div>
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_precat_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_precat_dialog.tt2
new file mode 100644 (file)
index 0000000..fc14ec3
--- /dev/null
@@ -0,0 +1,44 @@
+<!-- edit bucket dialog -->
+<form ng-submit="ok(precatArgs)" role="form">
+  <div class="">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" 
+          ng-click="cancel()" aria-hidden="true">&times;</button>
+        <h4 class="modal-title">
+          [% l('Barcode "{{precatArgs.copy_barcode}}" was mis-scanned or is a non-cataloged item.') %]
+        </h4>
+      </div>
+      <div class="modal-body">
+        <div class="form-group">
+          <label for="precat-title">[% l('Title') %]</label>
+          <input type="text" class="form-control" focus-me='focusMe' required
+            id="precat-title" ng-model="precatArgs.dummy_title" placeholder="[% l('Title...') %]"/>
+        </div>
+        <div class="form-group">
+          <label for="precat-author">[% l('Author') %]</label>
+          <input type="text" class="form-control" id="precat-author"
+            ng-model="precatArgs.dummy_author" placeholder="[% l('Author...') %]"/>
+        </div>
+        <div class="form-group">
+          <label for="precat-isbn">[% l('ISBN') %]</label>
+          <input type="text" class="form-control" id="precat-isbn"
+            ng-model="precatArgs.dummy_isbn" placeholder="[% l('ISBN...') %]"/>
+        </div>
+        <div class="form-group">
+          <label for="precat-circmod">[% l('Circulation Modifier') %]</label>
+          <select class="form-control" id="precat-circmod" 
+            ng-model="precatArgs.circ_modifier">
+            <option ng-repeat="mod in circModifiers" 
+              value="{{mod.code()}}">{{mod.name()}}</option>
+          </select>
+        </div>
+      </div>
+      <div class="modal-footer">
+        <input type="submit" class="btn btn-primary" value="[% l('Precat Checkout') %]"/>
+        <button class="btn btn-warning" ng-click="cancel()"
+            ng-class="{disabled : actionPending}">[% l('Cancel') %]</button>
+      </div>
+    </div> <!-- modal-content -->
+  </div> <!-- modal-dialog -->
+</form>
diff --git a/Open-ILS/src/templates/staff/circ/share/t_transit_dialog.tt2 b/Open-ILS/src/templates/staff/circ/share/t_transit_dialog.tt2
new file mode 100644 (file)
index 0000000..1491fb2
--- /dev/null
@@ -0,0 +1,65 @@
+<div class="">
+  <div class="">
+    <div class="modal-header">
+      <button type="button" class="close" 
+        ng-click="ok()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Transit Slip') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div>
+        <span>[% l('Destination') %]</span>
+        <strong>{{dest_location.shortname}}</strong>
+      </div>
+      <br/>
+      <div>
+        <address>
+          <strong>{{dest_location.name}}</strong><br>
+          {{dest_address.street1}} {{dest_address.street2}}<br/>
+          {{dest_address.city}}, {{dest_address.state}} {{dest_address.post_code}}<br/>
+          <abbr title="[% l('Phone') %]">P:</abbr> {{dest_location.phone}}
+        </address>
+      </div>
+      <div>
+        <span>[% l('Item Barcode:') %]</span>
+        <span>{{copy.barcode}}</span>
+      </div>
+      <div>
+        <span>[% l('Title:') %]</span>
+        <span>{{title}}</span>
+      </div>
+      <div>
+        <span>[% l('Author:') %]</span>
+        <span>{{author}}</span>
+      </div>
+      <div ng-if="patron">
+        <br/>
+        <div>[% |l %]
+          Hold for patron {{patron.family_name}}, 
+          {{patron.first_given_name}} {{patron.second_given_name}}
+          [% END %]
+        </div>
+        <div>
+          <span>[% l('Patron Barcode:') %]</span>
+          <span>{{patron.card.barcode}}</span>
+        </div>
+        <br/>
+        <div>
+          <span>[% l('Request Date:') %]</span>
+          <span>{{hold.request_time | date:'shortDate'}}</span>
+        </div>
+      </div>
+      <div>
+        <div>
+          <span>[% l('Slip Date:') %]</span>
+          <span>{{today | date:'shortDate'}}</span>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="button" class="btn btn-primary"
+        ng-click="print()" value="[% l('Print') %]"/>
+      <input type="submit" class="btn btn-warning"
+        ng-click="ok()" value="[% l('Do Not Print') %]"/>
+    </div>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/config.tt2 b/Open-ILS/src/templates/staff/config.tt2
new file mode 100644 (file)
index 0000000..c563d7a
--- /dev/null
@@ -0,0 +1,13 @@
+[%- 
+
+# FIXME: update via build process
+EVERGREEN_VERSION='0.0.1' 
+
+# create script / css refs to individual files instead of using
+# compressed build files.  Use this for development and debugging.
+EXPAND_WEB_IMPORTS = 1; 
+
+# path to build files (js, css, fonts)
+WEB_BUILD_PATH = ctx.media_prefix _ '/js/ui/default/staff/build/';
+
+%]
diff --git a/Open-ILS/src/templates/staff/css/circ.css.tt2 b/Open-ILS/src/templates/staff/css/circ.css.tt2
new file mode 100644 (file)
index 0000000..8d6c139
--- /dev/null
@@ -0,0 +1,60 @@
+/** style to make a grid look like a striped table */
+#patron-summary-grid div.row {padding: 3px; border-right: 2px solid rgb(248, 248, 248);}
+#patron-summary-grid div.row:nth-child(odd) {background-color: rgb(248, 248, 248);}
+
+/* there are bootstrap tyles for error, warning, etc., 
+but the ones I'm finding aren't quite cutting it..*/
+.patron-summary-alert {color: red; font-weight:bold}
+.patron-summary-alert-small {color: red}
+.patron-summary-divider { border-top: 1px solid #CCC}
+.patron-summary-act-link {font-size: .8em;}
+
+/* FIXME: use .barcode instead */
+#patron-checkout-barcode,
+#patron-renewal-barcode,
+#patron-checkin-barcode { width: 16em; }
+
+#patron-search-form div.form-group {
+  margin-bottom: 5px;
+}
+
+/* let search form elements fill their containers w/ slight padding */
+#patron-search-form-row {margin-left: 0px;}
+#patron-search-form div.col-md-2 { padding: 2px; }
+#patron-search-form input:not([type="checkbox"]) { width: 100%; }
+#patron-search-form .eg-org-selector,
+#patron-search-form .eg-org-selector button,
+#patron-search-form .patron-search-selector,
+  #patron-search-form .patron-search-selector button { 
+  width: 100%; 
+  text-align: left
+}
+
+
+#patron-payments-spreadsheet {
+  margin-top: 10px;
+  padding-top: 10px;
+  border-top: 1px solid #aaa;
+}
+
+#patron-payments-spreadsheet .flex-cell {
+  margin: 2px;
+}
+
+#patron-payments-spreadsheet .flex-cell.well {
+  min-height: 1.5em;
+  margin-bottom: 0px; /* bootstrap default is 20px */
+}
+
+#hold-notify-settings div.row { margin-top: 12px; }
+#hold-notify-settings div.row:not(.header-row):nth-child(odd) {
+  background-color: rgb(248, 248, 248);
+}
+#hold-notify-settings div.row:not(.header-row) {
+  border-bottom: 1px solid #CCC;
+}
+
+
+[%# 
+vim: ft=css 
+%]
diff --git a/Open-ILS/src/templates/staff/css/print.css.tt2 b/Open-ILS/src/templates/staff/css/print.css.tt2
new file mode 100644 (file)
index 0000000..5410ba9
--- /dev/null
@@ -0,0 +1,13 @@
+
+/* hide everything but the print div */
+head { display: none; } /* just to be safe */
+body div:not([id="print-div"]) { display:none }
+
+div { display: none }
+#print-div { display: block }
+#print-div div { display: block }
+#print-div pre { border: none }
+
+[%# 
+vim: ft=css 
+%]
diff --git a/Open-ILS/src/templates/staff/css/style.css.tt2 b/Open-ILS/src/templates/staff/css/style.css.tt2
new file mode 100644 (file)
index 0000000..300668c
--- /dev/null
@@ -0,0 +1,412 @@
+/* --------------------------------------------------------------------------
+ * Simple default navbar style adjustements to apply the Evergreen color.
+ * TODO: style other components to match EG color scheme
+ */
+#top-navbar.navbar-default {
+    background: -webkit-linear-gradient(#00593d, #007a54);
+    background-color: #007a54;
+    color: #fff;
+}
+#top-navbar.navbar-default .navbar-nav>li>a {
+    color: #fff;
+}
+#top-navbar.navbar-default .navbar-nav>li>a:hover {
+    color: #ddd;
+}
+#top-navbar.navbar-default .navbar-nav>.dropdown>a .caret {
+    border-top-color: #fff;
+    border-bottom-color: #fff;
+}
+#top-navbar.navbar-default .navbar-nav>.dropdown>a:hover .caret {
+    border-top-color: #ddd;
+    border-bottom-color: #ddd;
+}
+
+/* status bar along the bottom of the page ------------------------ */
+/* decrease padding to decrease overall height */
+
+/** TODO:move status bar items into navbar config entry (top-right)
+ * to avoid body padding weirdness.  Or if we want a permenently
+ * visible status bar, maybe put it just below the navbar.. */
+
+/* bottom padding ensures no body content is hidden behind the status
+ * bar.  When content reaches the status bar a scroll bar appears */
+/*body { padding-bottom: 26px; }*/
+
+#status-bar {
+  min-height:1.8em !important;
+}
+#status-bar > ul {
+  margin-right:6px; 
+}
+#status-bar li {
+  padding-left: 10px;
+}
+#status-bar > li > a {
+  padding-top:5px !important; 
+  padding-bottom:5px !important;
+}
+.status-bar-connected {
+  color: rgb(92, 184, 92); /* success */
+}
+
+/* --------------------------------------------------------------------------
+ * Structural modifications
+ */
+
+#top-content-container {
+    /* allow the primary container to occupy most of the page,
+     * but leave some narrow gutters along the side, much 
+     * narrower than the default Bootstrapp container gutters.
+     */
+    width: 95%;
+}
+
+
+/* --------------------------------------------------------------------------
+ * Temporaray local CSS required to make angular-ui-bootstrap
+ * version 0.6.0 look right with Bootstrap CSS 3.0
+ */
+.nav, .pagination, .carousel a { cursor: pointer; }
+/*
+.modal {
+    display: block;
+    height: 0;
+    overflow: visible;
+}
+.modal-body:before,
+.modal-body:after {
+    display: table;
+    content: " ";
+}
+.modal-header:before,
+.modal-header:after {
+    display: table;
+    content: " ";
+}
+*/
+
+/* --------------------------------------------------------------------------
+/* Form Validation CSS - http://docs.angularjs.org/guide/forms
+ * TODO: these colors are harsh and don't fit the EG color scheme
+ */
+.form-validated input.ng-invalid.ng-dirty {
+  background-color: #FA787E;
+}
+.form-validated input.ng-valid.ng-dirty {
+  background-color: #78FA89;
+}
+
+/* --------------------------------------------------------------------------
+ * Local style
+ */
+
+#splash-nav .panel-body div {
+    padding-bottom: 10px;
+}
+
+table.list tr.selected td { /* deprecated? */
+    color: #2a6496;
+    background-color: #F5F5F5;
+}
+
+.pad-horiz {padding : 0px 10px 0px 10px; }
+.pad-vert {padding : 20px 0px 10px 0px;}
+.pad-left {padding-left: 10px;}
+.pad-right {padding-right: 10px;}
+.pad-all-min {padding : 5px; }
+.pad-all {padding : 10px; }
+
+#print-div { display: none; }
+
+/* by default, give all tab panes some top padding */
+.tab-pane { padding-top: 20px; }
+
+.nav-pills-like-tabs {
+    border-bottom:1px solid #CCC;
+}
+
+.btn-pad {
+  /* sometimes you don't want buttons scrunched together -- add some margin */
+  margin-left: 10px;
+}
+
+.strong-text {
+  font-weight: bold;
+}
+.strong-text-1 {
+  font-size: 110%;
+  font-weight: bold;
+}
+.strong-text-2 {
+  font-size: 120%;
+  font-weight: bold;
+}
+.strong-text-3 {
+  font-size: 130%;
+  font-weight: bold;
+}
+.strong-text-4 {
+  font-size: 140%;
+  font-weight: bold;
+}
+
+.currency-input {
+  width: 8em;
+}
+
+/* barcode inputs are everywhere.  Let's have a consistent style. */
+.barcode { width: 16em !important; }
+
+/* bootstrap alerts are heavily padded.  use this to reduce */
+.alert-less-pad {padding: 5px;}
+
+/* text displayed inside a <progressbar>, typically the max/progress values */
+.progressbar-text {
+  color:black;
+  white-space:nowrap;
+}
+
+/* embedded UI iframe */
+.eg-embed-frame {
+  width: 100%;
+}
+.eg-embed-frame iframe {
+  width: 100%;
+  border: none;
+  margin: 0px;
+  padding: 0px;
+}
+
+/* ----------------------------------------------------------------------
+ * Grid
+ * ---------------------------------------------------------------------- */
+
+.eg-grid-primary-label {
+  font-weight: bold;
+  font-size: 120%;
+}
+
+/* odd/even row styling */
+.eg-grid-content-body > div:nth-child(odd):not(.eg-grid-row-selected) {
+  background-color: rgb(248, 248, 248);
+}
+
+.eg-grid-row {
+  width: 100%;
+  display: flex;
+  border: 1px solid #ccc;
+}
+
+.eg-grid-row:not(.eg-grid-header-row):not(.eg-grid-conf-row) {
+  /* TODO: remove, pretty sure this is no longer needed w/ nowrap */
+  /*height: 1.8em;*/
+}
+
+.eg-grid-action-row {
+  border: none;
+  /* margin should not have to be this large; something's up */
+  margin-bottom: 12px;
+}
+
+.eg-grid-header-row { 
+  font-weight: bold; 
+}
+
+.eg-grid-header-row > .eg-grid-cell {
+  border-right: 1px solid #CCC;
+  text-align: center;
+
+  /* vertically align header cell text by treating 
+     each header cell as a vertical flex container */
+  display:flex;
+  flex-direction:column;
+  justify-content:flex-end;
+}
+
+.eg-grid-cell {
+  /* avoid text flowing into adjacent cells */
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+
+/* in config display, make cells more obvious */
+.eg-grid-as-conf .eg-grid-row {
+  border: 1px solid #777;
+}
+.eg-grid-as-conf .eg-grid-cell {
+  border-right: 1px solid #777;
+}
+
+/* stock columns need fixed-width controls */
+.eg-grid-cell-stock {
+  width: 2.2em;
+  text-align: center;
+}
+
+/* the conf header must be twice the stock flex */
+.eg-grid-cell-conf-header {
+  width: 4.4em;
+  font-weight: bold;
+}
+
+.eg-grid-row-selected {
+  color: rgb(51, 51, 51);
+  background-color: rgb(201, 221, 225);
+  border-bottom: 1px solid #888;
+}
+
+/* Improve ::selection styling by only allowing selection on text
+ * content cells within the main body of the grid.  Otherwise, the browser 
+ * styles row background and text (all dark blue?) when shift-click or 
+ * click-drag is used.
+ */
+.eg-grid-content-body .eg-grid-row {
+  user-select:none;
+  -moz-user-select: none;
+  -webkit-user-select: none;
+}
+.eg-grid-content-body .eg-grid-cell-content {
+  user-select:text;
+  -moz-user-select: text;
+  -webkit-user-select: text;
+}
+.eg-grid-cell-content::-moz-selection {
+  color: rgb(51, 51, 51);
+  background: rgb(201, 221, 225);
+  border-bottom: 1px solid #888;
+}
+.eg-grid-cell-content::selection {
+  color: rgb(51, 51, 51);
+  background: rgb(201, 221, 225);
+  border-bottom: 1px solid #888;
+}
+
+.eg-grid-conf-cell-entry {
+  width:98%;
+  text-align:center;
+  padding: 3px;
+}
+
+.eg-grid-conf-cell-entry:not(:first-child) {
+  border-top:1px solid #ccc;
+}
+
+.eg-grid-conf-row {
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+
+.eg-grid-conf-row:first-child {
+  /* alignment fix; account for one missing border */
+  padding-right: 1px;
+}
+
+.eg-grid-column-move-handle:hover {
+  cursor: move;
+}
+
+.eg-grid-column-move-handle-active,
+.eg-grid-column-move-handle-active:active {
+  /* similar to label-primary, sans padding */
+  background-color: rgb(66, 139, 202);
+  color: #fff;
+}
+
+.eg-grid-col-hover {
+  /* similar to label-success, sans padding */
+  background-color: rgb(92, 184, 92);
+  color: #fff;
+}
+
+.eg-grid-column-resize-handle {
+  height: 100%;
+}
+.eg-grid-column-resize-handle:hover {
+  cursor: col-resize;
+}
+
+/* for these to be useful, they would have to be applied 
+ * to the dragover targets.  not yet done */
+.eg-grid-column-resize-handle-west {
+  cursor: w-resize;
+}
+.eg-grid-column-resize-handle-east {
+  cursor: e-resize;
+}
+
+.eg-grid-menu-item {
+  margin-right: 10px;
+}
+
+
+/* hack to make the header columns line up with the content columns
+   when the scroll bar is visible along the right side of the content
+   columns. TODO: if this varies enough by browser, we'll need to
+   calculate the width instead. */
+/*
+.eg-grid-scroll > .eg-grid-header-row, 
+.eg-grid-scroll > .eg-grid-conf-row { 
+  padding-right: 15px;
+}
+.eg-grid-scroll > .eg-grid-content-body {
+  overflow-y:scroll; 
+  height: 600px; 
+}
+*/
+.eg-grid-column-picker {
+  height: auto;
+  max-height: 400px;
+  overflow: auto;
+  box-shadow: none;
+}
+
+
+/* ----------------------------------------------------------------------
+ * /Grid
+ * ---------------------------------------------------------------------- */
+
+
+/* simple flex container for consistent-width cell-based structures */
+.flex-container-striped > .flex-row:nth-child(odd) {
+  background-color: #f5f5f5;
+}
+.flex-container-bordered .flex-cell {
+  border-bottom: 1px solid #ddd;
+}
+.flex-row {
+  display: flex;
+}
+.flex-row.padded div {
+  padding: 5px;
+}
+.flex-row.left-anchored > div {
+  margin-right: 10px;
+}
+.flex-cell {
+  flex: 1;
+  padding: 4px; /* bootstrap default is much bigger */
+}
+.flex-cell.well {
+  min-height: 2.5em; /* don't let empty wells scrunch down */
+  margin-bottom: 5px; /* bootstrap default is 20px */
+}
+.flex-2 { /* meh, convience */
+  flex: 2;
+}
+
+/* TODO: match media size to Bootstrap "md" col resizing */
+@media all and (max-width: 800px) {
+  .flex-row {
+    flex-direction: column;
+  }
+  .eg-grid-row {
+    flex-direction: column;
+  }
+}
+
+
+[%# 
+vim: ft=css 
+%]
diff --git a/Open-ILS/src/templates/staff/index.tt2 b/Open-ILS/src/templates/staff/index.tt2
new file mode 100644 (file)
index 0000000..b2e25f8
--- /dev/null
@@ -0,0 +1,17 @@
+[%
+  WRAPPER "staff/base.tt2";
+  ctx.page_title = l("Home"); 
+  ctx.page_app = "egHome";
+%]
+
+[% BLOCK APP_JS %]
+<!-- needed for login -->
+<script src="[% ctx.media_prefix %]/js/dojo/opensrf/md5.js"></script>
+<!-- splash / login page app -->
+<script src="[% ctx.media_prefix %]/js/ui/default/staff/app.js"></script>
+[% END %]
+
+<div ng-view></div> 
+
+[% END %]
+
diff --git a/Open-ILS/src/templates/staff/navbar.tt2 b/Open-ILS/src/templates/staff/navbar.tt2
new file mode 100644 (file)
index 0000000..6d0e6d8
--- /dev/null
@@ -0,0 +1,244 @@
+<!-- 
+  main navigation bar
+    
+  note the use of target="_self" for navigation links.
+  this tells angular to treat the href as a new page 
+  and not an intra-app route.  This is necessary when
+  moving between applications.
+
+  For icons, see http://getbootstrap.com/components/#glyphicons
+-->
+
+<div id="top-navbar" role="navigation"
+  class="navbar navbar-default navbar-static-top" role="navigation">
+
+  <!-- navbar-header here needed for supporting angular-ui-bootstrap -->
+  <div class="navbar-header">
+    <button type="button" class="navbar-toggle" 
+        ng-init="navCollapsed = true" ng-click="navCollapsed = !navCollapsed">
+      <span class="sr-only">[% l('Toggle navigation') %]</span>
+      <span class="icon-bar"></span>
+      <span class="icon-bar"></span>
+      <span class="icon-bar"></span>
+    </button>
+  </div>
+
+  <div class="navbar-collapse collapse" ng-class="!navCollapsed && 'in'">
+    <ul class="nav navbar-nav">
+      <li><a href='./' title="[% l('Home') %]" target="_self"
+        class="glyphicon glyphicon-home"></a><li>
+
+      <!-- search -->
+      <li class="dropdown">
+        <a href="javascript:;" class="dropdown-toggle"
+          data-toggle="dropdown">[% l('Search') %]
+          <b class="caret"></b>
+        </a>
+        <ul class="dropdown-menu">
+          <li>
+            <a href="./circ/patron/search" target="_self"
+              eg-accesskey="[% l('alt+s') %]" 
+              eg-accesskey-desc="[% l('Patron search by name, address, etc.') %]">
+              <span class="glyphicon glyphicon-user"></span>
+              <span eg-accesskey-label>[% l('Search for Patrons') %]</span>
+            </a>
+          </li>
+          <li>
+            <a href="./cat/item/search" target="_self">
+              <span class="glyphicon glyphicon-barcode"></span>
+              <span>[% l('Search for Copies by Barcode') %]</span>
+            </a>
+          </li>
+        </ul>
+      </li>
+
+
+      <!-- circulation -->
+      <li class="dropdown">
+        <a href="javascript:;" class="dropdown-toggle"
+          data-toggle="dropdown">[% l('Circulation') %]
+          <b class="caret"></b>
+        </a>
+
+        <ul class="dropdown-menu">
+          <li>
+            <a href="./circ/patron/bcsearch" target="_self">
+              <span class="glyphicon glyphicon-export"></span>
+              [% l('Check Out') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/checkin/checkin" target="_self">
+              <span class="glyphicon glyphicon-import"></span>
+              [% l('Check In') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/checkin/capture" target="_self">
+              <span class="glyphicon glyphicon-pushpin"></span>
+              [% l('Capture Holds') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/holds/pull" target="_self">
+              <span class="glyphicon glyphicon-th-list"></span>
+              [% l('Pull List for Hold Requests') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/renew/renew" target="_self">
+              <span class="glyphicon glyphicon-refresh"></span>
+              [% l('Renew Items') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/register" target="_self">
+              <span class="glyphicon glyphicon-user"></span>
+              [% l('Register Patron') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/last" target="_self">
+              <span class="glyphicon glyphicon-share-alt"></span>
+              [% l('Retrieve Last Patron') %]
+            </a>
+          </li>
+          <li>
+            <a href="./circ/patron/pending/list" target="_self">
+              <span class="glyphicon glyphicon-thumbs-up"></span>
+              [% l('Pending Patrons') %]
+            </a>
+          </li>
+          <li class="divider"></li>
+          <li>
+            <a href="./circ/patron/credentials" target="_self">
+              <span class="glyphicon glyphicon-ok"></span>
+              <span>[% l('Verify Credentials') %]</span>
+            </a>
+          </li>
+          <li>
+            <a href="./circ/in_house_use/index" target="_self">
+              <span class="glyphicon glyphicon-pencil"></span>
+              <span>[% l('Record In-House Use') %]</span>
+            </a>
+          </li>
+          <li>
+            <a href="./circ/holds/shelf" target="_self">
+              <span class="glyphicon glyphicon-tasks"></span>
+              <span>[% l('Holds Shelf') %]</span>
+            </a>
+          </li>
+          <li class="divider"></li>
+          <li>
+            <a href="./cat/item/replace_barcode/index" target="_self">
+              <span class="glyphicon glyphicon-barcode"></span>
+              <span>[% l('Replace Barcode') %]</span>
+            </a>
+          </li>
+          <li>
+            <a href="./cat/item/missing_pieces" target="_self">
+              <span class="glyphicon glyphicon-th"></span>
+              <span>[% l('Scan Item as Missing Pieces') %]</span>
+            </a>
+          </li>
+        </ul>
+      </li><!-- circ -->
+
+      <!-- cataloging -->
+      <li class="dropdown">
+        <a href="javascript:;" class="dropdown-toggle" 
+          data-toggle="dropdown">[% l('Cataloging') %]
+            <b class="caret"></b>
+        </a>
+        <ul class="dropdown-menu">
+          <li>
+            <a href="./cat/catalog/index" target="_self">
+              <span class="glyphicon glyphicon-search"></span>
+              [% l('Search the Catalog') %]
+            </a>
+          </li>
+          <li>
+            <a href="./cat/bucket/record/view" target="_self">
+              <span class="glyphicon glyphicon-list-alt"></span>
+              [% l('Record Buckets') %]
+            </a>
+          </li>
+       </ul>
+      </li>
+
+      <!-- admin -->
+      <li class="dropdown">
+        <a href="javascript:;" class="dropdown-toggle" 
+          data-toggle="dropdown">[% l('Administration') %]
+            <b class="caret"></b>
+        </a>
+        <ul class="dropdown-menu">
+          <li>
+            <a href="./admin/workstation/index" target="_self">
+              <span class="glyphicon glyphicon-hdd"></span>
+              [% l('Workstation') %]
+            </a>
+          </li>
+          <li>
+            <a href="./admin/user_perms" target="_self">
+              <span class="glyphicon glyphicon-user"></span>
+              [% l('User Permission Editor') %]
+            </a>
+          </li>
+        </ul> <!-- admin dropdown -->
+      </li>
+    </ul> <!-- end left side entries -->
+
+    <!-- entries along the right side of the navbar -->
+    <ul class="nav navbar-nav navbar-right" style='margin-right: 6px;'>
+      <li>
+        <a ng-cloak ng-show="username" 
+          ng-init="workstation = '[% l('<no workstation>') %]'">
+            [% l('{{username}} @ {{workstation}}') %]
+        </a>
+      </li>
+
+      <!-- locale selector.  
+        only shown if multiple locales are registered -->
+      [% IF ctx.locales.keys.size > 1 %]
+      <li class="dropdown">
+        <a href='' class="dropdown-toggle" data-toggle="dropdown">
+            [% lcl = ctx.locale;  ctx.locales.$lcl %]
+            <span class="glyphicon glyphicon-flag"></span>
+        </a>
+        <ul class="dropdown-menu">
+        [% FOR locale IN ctx.locales.keys.sort %]
+          <!-- disable the selected locale -->
+          <li ng-class="{disabled : '[% ctx.locale %]'=='[% locale %]'}">
+            <a href="" ng-click="applyLocale('[% locale %]')">
+                [% ctx.locales.$locale %]
+            </a>
+          </li>
+        [% END %]
+        </ul>
+      </li>
+      [% END %]
+
+      <li class="dropdown" ng-show="username">
+        <a href='' class="dropdown-toggle glyphicon glyphicon-list" 
+          data-toggle="dropdown"></a>
+        <ul class="dropdown-menu">
+          <li class="disabled">
+            <a href="" ng-click="" target="_self">
+              <span class="glyphicon glyphicon-random"></span>
+              [% l('Change Operator') %]
+            </a>
+          </li>
+          <li>
+            <a href="./login" ng-click="logout()" target="_self">
+              <span class="glyphicon glyphicon-log-out"></span>
+              [% l('Log Out') %]
+            </a>
+          </li>
+        </ul>
+      </li>
+    </ul>
+  </div>
+</div>
+
+
diff --git a/Open-ILS/src/templates/staff/share/README b/Open-ILS/src/templates/staff/share/README
new file mode 100644 (file)
index 0000000..bcbddf5
--- /dev/null
@@ -0,0 +1,5 @@
+Location for globally shared template files.  These are generally used 
+by AngularJS directives.
+
+App-specific shared templates should live within the application's
+directory.
diff --git a/Open-ILS/src/templates/staff/share/print_templates/index.tt2 b/Open-ILS/src/templates/staff/share/print_templates/index.tt2
new file mode 100644 (file)
index 0000000..0bcedf0
--- /dev/null
@@ -0,0 +1,2 @@
+[% USE CGI %]
+[% l('Print Template Not Found: [_1]', CGI.url("-path",1,"-relative",1)) %]
diff --git a/Open-ILS/src/templates/staff/share/print_templates/t_bill_payment.tt2 b/Open-ILS/src/templates/staff/share/print_templates/t_bill_payment.tt2
new file mode 100644 (file)
index 0000000..fe6851a
--- /dev/null
@@ -0,0 +1,69 @@
+Welcome to {{current_location.name}}!<br/>
+A receipt of your  transaction:<hr/>
+
+<table style="width:100%"> 
+  <tr> 
+    <td>[% l('Original Balance:') %]</td> 
+    <td align="right">{{previous_balance | currency}}</td> 
+  </tr> 
+  <tr> 
+    <td>[% l('Payment Method:') %]</td> 
+    <td align="right">
+      <div ng-switch="payment_type">
+        <div ng-switch-when="cash_payment">[% l('Cash') %]</div>
+        <div ng-switch-when="check_payment">[% l('Check') %]</div>
+        <div ng-switch-when="credit_card_payment">[% l('Credit Card') %]</div>
+        <div ng-switch-when="credit_payment">[% l('Patron Credit') %]</div>
+        <div ng-switch-when="work_payment">[% l('Work') %]</div>
+        <div ng-switch-when="forgive_payment">[% l('Forgive') %]</div>
+        <div ng-switch-when="goods_payment">[% l('Goods') %]</div>
+      </div>
+    </td>
+  </tr> 
+  <tr> 
+    <td>[% l('Payment Received:') %]</td> 
+    <td align="right">{{payment_total | currency}}</td> 
+  </tr> 
+  <tr> 
+    <td>[% l('Payment Applied:') %]</td> 
+    <td align="right">{{payment_applied | currency}}</td> 
+  </tr> 
+  <tr> 
+    <td>[% l('Billings Voided:') %]</td> 
+    <td align="right">{{amount_voided | currency}}</td> 
+  </tr> 
+  <tr> 
+    <td>[% l('Change Given:') %]</td> 
+    <td align="right">{{change_given | currency}}</td> 
+  </tr> 
+  <tr> 
+    <td>[% l('New Balance:') %]</td> 
+    <td align="right">{{new_balance | currency}}</td> 
+  </tr> 
+</table> 
+
+<p>[% l('Note: [_1]', '{{payment_note}}') %]</p>
+
+<p>
+[% l('Specific Bills') %]
+  <blockquote>
+    <div ng-repeat="payment in payments">
+      <table style="width:100%">
+        <tr>
+          <td>[% l('Bill # [_1]', '{{payment.xact.id}}') %]</td>
+          <td>{{payment.xact.summary.last_billing_type}}</td>
+          <td>[% l('Received: [_1]', '{{payment.amount | currency}}') %]</td>
+        </tr>
+        <tr>
+          <td colspan="5">
+            {{payment.xact.copy_barcode}} {{payment.xact.title}}
+          </td>
+        </tr>
+      </table>
+      <br/>
+    </div>
+  </blockquote>
+</p> 
+<hr/>
+<br/><br/> 
+{{current_location.shortname}} {{today | date:'short'}}
diff --git a/Open-ILS/src/templates/staff/share/print_templates/t_bills_current.tt2 b/Open-ILS/src/templates/staff/share/print_templates/t_bills_current.tt2
new file mode 100644 (file)
index 0000000..c99cb4d
--- /dev/null
@@ -0,0 +1,49 @@
+Welcome to {{current_location.name}}!<br/>
+You have the following bills:
+<hr/>
+<dl>
+  <div ng-repeat="xact in transactions">
+    <dt><b>Bill #{{xact.id}}</b></dt>
+    <dd>
+    <table> 
+      <tr valign="top">
+        <td>[% l('Date:') %]</td>
+        <td>{{xact.xact_start | date:'short'}}</td>
+      </tr> 
+      <tr valign="top">
+        <td>[% l('Type') %]:</td>
+        <td>{{xact.summary.xact_type}}</td>
+      </tr> 
+      <tr valign="top">
+        <td>[% l('Last Billing') %]:</td>
+        <td>{{xact.summary.last_billing_type}}<br/>
+            {{xact.summary.last_billing_note}}
+        </td>
+      </tr> 
+      <tr valign="top">
+        <td>[% l('Total Billed') %]:</td>
+        <td>{{xact.summary.total_owed | currency}}</td>
+      </tr> 
+      <tr valign="top">
+        <td>[% l('Last Payment') %]:</td>
+        <td>{{xact.summary.last_payment_type}}<br/>
+            {{xact.summary.last_payment_note}}
+        </td>
+      </tr> 
+      <tr valign="top">
+        <td>[% l('Total Paid') %]:</td>
+        <td>{{xact.summary.total_paid | currency}}</td>
+      </tr> 
+      <tr valign="top">
+        <td><b>[% l('Balance') %]:</b></td>
+        <td><b>{{xact.summary.balance_owed | currency}}</b></td>
+      </tr> 
+    </table>
+    </dd>
+    <br/>
+  </div><!-- ng-repeat -->
+</dl>
+<hr/>
+{{current_location.shortname}} {{today | date:'short'}}
+<br/><br/>
+
diff --git a/Open-ILS/src/templates/staff/share/print_templates/t_bills_historical.tt2 b/Open-ILS/src/templates/staff/share/print_templates/t_bills_historical.tt2
new file mode 100644 (file)
index 0000000..c99cb4d
--- /dev/null
@@ -0,0 +1,49 @@
+Welcome to {{current_location.name}}!<br/>
+You have the following bills:
+<hr/>
+<dl>
+  <div ng-repeat="xact in transactions">
+    <dt><b>Bill #{{xact.id}}</b></dt>
+    <dd>
+    <table> 
+      <tr valign="top">
+        <td>[% l('Date:') %]</td>
+        <td>{{xact.xact_start | date:'short'}}</td>