Merge branch 'master' of git+ssh://yeti.esilibrary.com/home/evergreen/evergreen-equin...
authorMike Rylander <mrylander@gmail.com>
Fri, 13 May 2011 15:30:21 +0000 (11:30 -0400)
committerMike Rylander <mrylander@gmail.com>
Fri, 13 May 2011 15:30:21 +0000 (11:30 -0400)
288 files changed:
Open-ILS/examples/apache/eg_vhost.conf
Open-ILS/examples/fm_IDL.xml
Open-ILS/examples/oils_web.xml.example
Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm [new file with mode: 0644]
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm [new file with mode: 0644]
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Container.pm [new file with mode: 0644]
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm [new file with mode: 0644]
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm [new file with mode: 0644]
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm [new file with mode: 0644]
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGWeb.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGWeb/CGI_utf8.pm [new file with mode: 0644]
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGWeb/I18NFilter.pm [new file with mode: 0644]
Open-ILS/src/support-scripts/test-scripts/unapi_bench.pl [new file with mode: 0755]
Open-ILS/web/css/skin/default/opac/contentslider.css [new file with mode: 0644]
Open-ILS/web/css/skin/default/opac/semiauto.css [new file with mode: 0644]
Open-ILS/web/css/skin/default/opac/style.css [new file with mode: 0644]
Open-ILS/web/images/KCLS_logo_horiz.gif [new file with mode: 0644]
Open-ILS/web/images/acct-btn-hover.png [new file with mode: 0644]
Open-ILS/web/images/acct-btn.png [new file with mode: 0644]
Open-ILS/web/images/acct_checked_out_off.gif [new file with mode: 0644]
Open-ILS/web/images/acct_checked_out_on.gif [new file with mode: 0644]
Open-ILS/web/images/acct_favs_off.gif [new file with mode: 0644]
Open-ILS/web/images/acct_favs_on.gif [new file with mode: 0644]
Open-ILS/web/images/acct_fines_off.jpg [new file with mode: 0644]
Open-ILS/web/images/acct_fines_on.jpg [new file with mode: 0644]
Open-ILS/web/images/acct_holds_off.gif [new file with mode: 0644]
Open-ILS/web/images/acct_holds_on.gif [new file with mode: 0644]
Open-ILS/web/images/acct_lists_off.gif [new file with mode: 0644]
Open-ILS/web/images/acct_lists_on.gif [new file with mode: 0644]
Open-ILS/web/images/acct_payments_off.jpg [new file with mode: 0644]
Open-ILS/web/images/acct_payments_on.jpg [new file with mode: 0644]
Open-ILS/web/images/acct_prefs_off.gif [new file with mode: 0644]
Open-ILS/web/images/acct_prefs_on.gif [new file with mode: 0644]
Open-ILS/web/images/acct_sum_fines_bl.png [new file with mode: 0644]
Open-ILS/web/images/acct_sum_fines_br.png [new file with mode: 0644]
Open-ILS/web/images/acct_sum_fines_tl.png [new file with mode: 0644]
Open-ILS/web/images/acct_sum_fines_tr.png [new file with mode: 0644]
Open-ILS/web/images/acct_summary_off.gif [new file with mode: 0644]
Open-ILS/web/images/acct_summary_on.gif [new file with mode: 0644]
Open-ILS/web/images/add_mylist.gif [new file with mode: 0644]
Open-ILS/web/images/add_mylist_sel.gif [new file with mode: 0644]
Open-ILS/web/images/add_mylist_sel.kcls.gif [new file with mode: 0644]
Open-ILS/web/images/add_search_row_btn.gif [new file with mode: 0644]
Open-ILS/web/images/adv_row_close_btn.png [new file with mode: 0644]
Open-ILS/web/images/adv_search.png [new file with mode: 0644]
Open-ILS/web/images/adv_search_hover.png [new file with mode: 0644]
Open-ILS/web/images/adv_search_off.gif [new file with mode: 0644]
Open-ILS/web/images/adv_search_on.gif [new file with mode: 0644]
Open-ILS/web/images/another_search.png [new file with mode: 0644]
Open-ILS/web/images/another_search_hover.png [new file with mode: 0644]
Open-ILS/web/images/arrow-down.gif [new file with mode: 0644]
Open-ILS/web/images/arrow-right.gif [new file with mode: 0644]
Open-ILS/web/images/arrow-right.png [new file with mode: 0644]
Open-ILS/web/images/asknow_available.gif [new file with mode: 0644]
Open-ILS/web/images/banner-bg.png [new file with mode: 0644]
Open-ILS/web/images/banner1.jpg [new file with mode: 0644]
Open-ILS/web/images/btnCancel.png [new file with mode: 0644]
Open-ILS/web/images/btnSubmit.png [new file with mode: 0644]
Open-ILS/web/images/button-bg.png [new file with mode: 0644]
Open-ILS/web/images/cancel_btn.gif [new file with mode: 0644]
Open-ILS/web/images/cd-small.png [new file with mode: 0644]
Open-ILS/web/images/clipboard.png [new file with mode: 0644]
Open-ILS/web/images/dash-corner-left1.png [new file with mode: 0644]
Open-ILS/web/images/dash-corner-left2.png [new file with mode: 0644]
Open-ILS/web/images/dash-corner-mid1.png [new file with mode: 0644]
Open-ILS/web/images/dash-corner-mid2.png [new file with mode: 0644]
Open-ILS/web/images/dash-corner-right1.png [new file with mode: 0644]
Open-ILS/web/images/dash-corner-right2.png [new file with mode: 0644]
Open-ILS/web/images/dash-divider.jpg [new file with mode: 0644]
Open-ILS/web/images/dropdown-hover.gif [new file with mode: 0644]
Open-ILS/web/images/dropdown.gif [new file with mode: 0644]
Open-ILS/web/images/expert_search_off.gif [new file with mode: 0644]
Open-ILS/web/images/expert_search_on.gif [new file with mode: 0644]
Open-ILS/web/images/faqs-btn.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/a.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/c.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/d.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/e.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/f.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/g.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/i.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/j.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/k.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/m.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/o.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/p.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/r.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/item_type/t.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/2.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/5.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/a.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/b.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/c.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/d.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/e.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/f.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/h.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/i.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/j.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/k.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/l.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/m.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_downloadableebook.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_electronicgames.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_evideo.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_onlinejournal.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_player.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_podcasts.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_streamingaudio.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_streamingvideo.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/media_vhs.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/n.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/o.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/p.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/q.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/r.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/s.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/t.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/v.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/w.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/x.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/y.png [new file with mode: 0644]
Open-ILS/web/images/format_icons/mattype/z.png [new file with mode: 0644]
Open-ILS/web/images/go-btn-hover.png [new file with mode: 0644]
Open-ILS/web/images/go-btn.png [new file with mode: 0644]
Open-ILS/web/images/go_but_long.gif [new file with mode: 0644]
Open-ILS/web/images/golive.jpg [new file with mode: 0644]
Open-ILS/web/images/gray-arrow.png [new file with mode: 0644]
Open-ILS/web/images/green_check.png [new file with mode: 0644]
Open-ILS/web/images/header_left.gif [new file with mode: 0644]
Open-ILS/web/images/header_right.gif [new file with mode: 0644]
Open-ILS/web/images/hp-links-left.jpg [new file with mode: 0644]
Open-ILS/web/images/hp-links-mid.jpg [new file with mode: 0644]
Open-ILS/web/images/hp-links-right.jpg [new file with mode: 0644]
Open-ILS/web/images/locations.jpg [new file with mode: 0644]
Open-ILS/web/images/login-bg.jpg [new file with mode: 0644]
Open-ILS/web/images/login-bg2.jpg [new file with mode: 0644]
Open-ILS/web/images/login-box-bg.jpg [new file with mode: 0644]
Open-ILS/web/images/login-btn-hover.png [new file with mode: 0644]
Open-ILS/web/images/login-btn.gif [new file with mode: 0644]
Open-ILS/web/images/login-btn.png [new file with mode: 0644]
Open-ILS/web/images/login-btn2.png [new file with mode: 0644]
Open-ILS/web/images/logout-btn-hover.png [new file with mode: 0644]
Open-ILS/web/images/logout-btn.png [new file with mode: 0644]
Open-ILS/web/images/num_search_off.gif [new file with mode: 0644]
Open-ILS/web/images/num_search_on.gif [new file with mode: 0644]
Open-ILS/web/images/one_land.gif [new file with mode: 0644]
Open-ILS/web/images/pay-fines-btn-hover.png [new file with mode: 0644]
Open-ILS/web/images/pay-fines-btn.png [new file with mode: 0644]
Open-ILS/web/images/pay_fines_btn.gif [new file with mode: 0644]
Open-ILS/web/images/place_hold.gif [new file with mode: 0644]
Open-ILS/web/images/plus_sign.png [new file with mode: 0644]
Open-ILS/web/images/projectedmedia.jpg [new file with mode: 0644]
Open-ILS/web/images/question-mark.png [new file with mode: 0644]
Open-ILS/web/images/questions.png [new file with mode: 0644]
Open-ILS/web/images/rdetail_arrow.png [new file with mode: 0644]
Open-ILS/web/images/reset_form_btn.gif [new file with mode: 0644]
Open-ILS/web/images/reviews.gif [new file with mode: 0644]
Open-ILS/web/images/save-btn.png [new file with mode: 0644]
Open-ILS/web/images/save_btn.gif [new file with mode: 0644]
Open-ILS/web/images/search_btn.gif [new file with mode: 0644]
Open-ILS/web/images/small-rss.png [new file with mode: 0644]
Open-ILS/web/images/starz.png [new file with mode: 0644]
Open-ILS/web/images/sub_checked_hist_off.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_checked_hist_on.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_checked_out_off.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_checked_out_on.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_holds_hist_off.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_holds_hist_on.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_holds_off.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_holds_on.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_prefs_info_off.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_prefs_info_on.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_prefs_notify_off.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_prefs_notify_on.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_prefs_search_off.jpg [new file with mode: 0644]
Open-ILS/web/images/sub_prefs_search_on.jpg [new file with mode: 0644]
Open-ILS/web/images/submit_btn.gif [new file with mode: 0644]
Open-ILS/web/images/tool_back.gif [new file with mode: 0644]
Open-ILS/web/images/tool_back.png [new file with mode: 0644]
Open-ILS/web/images/tool_font.gif [new file with mode: 0644]
Open-ILS/web/images/tool_forward.gif [new file with mode: 0644]
Open-ILS/web/images/tool_forward.png [new file with mode: 0644]
Open-ILS/web/images/tool_help.gif [new file with mode: 0644]
Open-ILS/web/images/tool_help.png [new file with mode: 0644]
Open-ILS/web/images/tool_home.gif [new file with mode: 0644]
Open-ILS/web/images/tool_home.png [new file with mode: 0644]
Open-ILS/web/images/tool_mail.gif [new file with mode: 0644]
Open-ILS/web/images/tool_print.gif [new file with mode: 0644]
Open-ILS/web/images/tool_print.png [new file with mode: 0644]
Open-ILS/web/images/utils-corner-left.png [new file with mode: 0644]
Open-ILS/web/images/utils-corner-mid.png [new file with mode: 0644]
Open-ILS/web/images/utils-corner-right.jpg [new file with mode: 0644]
Open-ILS/web/images/utils-corner-right.png [new file with mode: 0644]
Open-ILS/web/images/utils-corner.jpg [new file with mode: 0644]
Open-ILS/web/images/view_my_list.png [new file with mode: 0644]
Open-ILS/web/images/view_my_list_hover.png [new file with mode: 0644]
Open-ILS/web/js/ui/default/opac/simple.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/opac/staff.js [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/base.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/common.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/home.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/login.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/marc_attrs.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/myopac/_links.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/myopac/bookbags.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/myopac/circs.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/myopac/fines.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/myopac/holds.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/myopac/main.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/myopac/prefs.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/myopac/update_email.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/place_hold.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/record.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac-poc/results.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/advanced.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/home.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/login.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/mylist.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/circ_history.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/circs.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/hold_history.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/holds.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/holds/edit.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/lists.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/main.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/main_payment_form.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/main_payments.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/main_refund_policy.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/prefs.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/prefs_notify.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/prefs_settings.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/update_email.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/update_password.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/myopac/update_username.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/advanced/global_row.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/advanced/search.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/anon_list.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/base.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/cn_browse.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/coded_value_selector.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/filtersort.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/footer.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/header.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/homesearch.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/js.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/login/form.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/login/help.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/login/password_hint.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/misc_util.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/myopac/base.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/myopac/main_base.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/myopac/prefs_base.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/myopac/prefs_hints.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/org_selector.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/place_hold.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/printnav.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/qtype_selector.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/record/authors.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/record/body.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/record/cn_details.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/record/copyinfo.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/record/extras.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/record/issues.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/record/subjects.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/record/summary.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/result/lowhits.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/result/lowhits_purchase.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/result/table.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/searchbar.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/tips.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/topnav.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/topnav_links.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/parts/topnav_logo.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/place_hold.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/record.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/opac/results.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/myopac/main_refund_policy.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/parts/footer.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/parts/homesearch.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/parts/login/help.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/parts/myopac/prefs_hints.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/parts/printnav.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/parts/result/lowhits_purchase.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/parts/topnav_links.tt2 [new file with mode: 0644]
Open-ILS/web/templates_kcls/default/opac/parts/topnav_logo.tt2 [new file with mode: 0644]

index 7fea97c..7fb1354 100644 (file)
@@ -169,26 +169,6 @@ RewriteRule . - [E=locale:%1]
 
 </Location>
 
-<Location /js/>
-    # ----------------------------------------------------------------------------------
-    # Some mod_deflate fun
-    # ----------------------------------------------------------------------------------
-    <IfModule mod_deflate.c>
-        SetOutputFilter DEFLATE
-
-        BrowserMatch ^Mozilla/4 gzip-only-text/html
-        BrowserMatch ^Mozilla/4\.0[678] no-gzip
-        BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
-
-        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
-
-        <IfModule mod_headers.c>
-            Header append Vary User-Agent env=!dont-vary
-        </IfModule>
-    </IfModule>
-
-</Location>
-
 # ----------------------------------------------------------------------------------
 # Force SSL on the OPAC's "My Account" page
 # ----------------------------------------------------------------------------------
@@ -554,7 +534,40 @@ RewriteRule ^/openurl$ ${openurl:%1} [NE,PT]
     Options +ExecCGI
     PerlSendHeader On
     allow from all
+    <IfModule mod_deflate.c>
+        SetOutputFilter DEFLATE
+        BrowserMatch ^Mozilla/4 gzip-only-text/html
+        BrowserMatch ^Mozilla/4\.0[678] no-gzip
+        BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
+        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
+        <IfModule mod_headers.c>
+            Header append Cache-Control "public"
+            Header append Vary User-Agent env=!dont-vary
+        </IfModule>
+    </IfModule>
 </Location>
+<LocationMatch ^/(images|css|js)/>
+    # should pick up the default expire time from eg.conf...
+    <IfModule mod_deflate.c>
+        SetOutputFilter DEFLATE
+        BrowserMatch ^Mozilla/4 gzip-only-text/html
+        BrowserMatch ^Mozilla/4\.0[678] no-gzip
+        BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
+        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
+        <IfModule mod_headers.c>
+            Header append Cache-Control "public"
+            Header append Vary User-Agent env=!dont-vary
+        </IfModule>
+    </IfModule>
+</LocationMatch>
+<Location /eg/opac>
+    PerlSetVar OILSWebContextLoader "OpenILS::WWW::EGCatLoader"
+    # Expire the HTML quickly since we're loading dynamic data for each page
+    ExpiresActive On
+    ExpiresByType text/html "access plus 5 seconds"
+</Location>
+
+
 # Note: the template processor will decline handling anything it does not
 # have an explicit configuration for, which means it will fall back to 
 # Apache to serve the file.  However, in the interest of speed, go ahead 
index 724e8f5..f71ddd6 100644 (file)
@@ -2262,6 +2262,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                        <field name="xact" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field name="grocery" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field name="circulation" oils_persist:virtual="true" reporter:datatype="link"/>
+                       <field name="reservation" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field name="billing_location" reporter:datatype="link"/>
                </fields>
                <links>
@@ -2269,6 +2270,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                        <link field="xact" reltype="might_have" key="id" map="" class="mbt"/>
                        <link field="circulation" reltype="might_have" key="id" map="" class="circ"/>
                        <link field="grocery" reltype="might_have" key="id" map="" class="mg"/>
+                       <link field="reservation" reltype="might_have" key="id" map="" class="bresv"/>
                        <link field="billing_location" reltype="has_a" key="id" map="" class="aou"/>
                </links>
        </class>
index 60f1573..0728082 100644 (file)
@@ -9,8 +9,24 @@
         files have the following filename extension -->
     <default_template_extension>tt2</default_template_extension>
 
-    <!-- media_prefix can be a remote server.  
-         E.g. <media_prefix>http://static.example.com/media</media_prefix> -->
+    <!-- Media Prefix.  Allows static files to be served from an alternate domain/server
+
+            Examples:
+
+                # local URL path
+                <media_prefix>/media</media_prefix> 
+
+                # server w/ path.  
+                <media_prefix>static.example.com/media</media_prefix> 
+
+                ===
+                In the first 2 examples, the request protocol (http vs https) will
+                match the protocol of the current page
+                ===
+
+                # full-qualified with static protocol
+                <media_prefix>http://static.example.com/media</media_prefix> 
+     -->
     <media_prefix/>
 
     <!-- If set to true, all output will be parsed as XML before delivery to the client.  
         XML parsing adds overhead, so this should only be used for debugging -->
     <force_valid_xml>false</force_valid_xml>
 
+    <!-- Turn on template-toolkit debugging, which reports on undefined blocks, macros, etc. -->
+    <debug_template>false</debug_template>
+
+    <!-- 
+        Supported locales.  Locales with no message catalog will use the native template strings.
+        All locales will fall back to native strings when a given string is not in the catalog
+    -->
+    <locales>
+        <en_US/>
+        <en_CA>/openils/var/data/locale/messages.en_CA.po</en_CA>
+        <fr_CA>/openils/var/data/locale/messages.fr_CA.po</fr_CA>
+    </locales>
+
     <!-- Where templates can be found.  Paths will be checked in the order entered here.
          It's possible to override individual or sets of templates by putting them into
          a path in front of the default template path -->
index 9b9bd13..864ef6e 100644 (file)
@@ -1815,39 +1815,31 @@ __PACKAGE__->register_method(
 );
        
 sub hold_request_count {
-       my( $self, $client, $login_session, $userid ) = @_;
-
-       my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
-               $login_session, $userid, 'VIEW_HOLD' );
-       return $evt if $evt;
-       
-
-       my $holds = $apputils->simple_scalar_request(
-                       "open-ils.cstore",
-                       "open-ils.cstore.direct.action.hold_request.search.atomic",
-                       { 
-                               usr => $userid,
-                               fulfillment_time => {"=" => undef },
-                               cancel_time => undef,
-                       }
-       );
+       my( $self, $client, $authtoken, $user_id ) = @_;
+    my $e = new_editor(authtoken => $authtoken);
+    return $e->event unless $e->checkauth;
 
-       my @ready;
-       for my $h (@$holds) {
-               next unless $h->capture_time and $h->current_copy;
+    $user_id = $e->requestor->id unless defined $user_id;
 
-               my $copy = $apputils->simple_scalar_request(
-                       "open-ils.cstore",
-                       "open-ils.cstore.direct.asset.copy.retrieve",
-                       $h->current_copy
-               );
+    if($e->requestor->id ne $user_id) {
+        my $user = $e->retrieve_actor_user($user_id);
+        return $e->event unless $e->allowed('VIEW_HOLD', $user->home_ou);
+    }
 
-               if ($copy and $copy->status == 8) {
-                       push @ready, $h;
-               }
-       }
+    my $holds = $e->json_query({
+        select => {ahr => ['shelf_time']},
+        from => 'ahr',
+        where => {
+            usr => $user_id,
+            fulfillment_time => {"=" => undef },
+            cancel_time => undef,
+        }
+    });
 
-       return { total => scalar(@$holds), ready => scalar(@ready) };
+       return { 
+        total => scalar(@$holds), 
+        ready => scalar(grep { $_->{shelf_time} } @$holds) 
+    };
 }
 
 __PACKAGE__->register_method(
index 8b29701..d21a8cc 100644 (file)
@@ -1818,5 +1818,61 @@ sub create_circ_chain_summary {
     return $obj;
 }
 
+
+# Returns "mra" attribute key/value pairs for a set of bre's
+# Takes a list of bre IDs, returns a hash of hashes,
+# {bre_id1 => {key1 => {code => value1, label => label1}, ...}...}
+my $ccvm_cache;
+sub get_bre_attrs {
+    my ($class, $bre_ids, $e) = @_;
+    $e = $e || OpenILS::Utils::CStoreEditor->new;
+
+    my $attrs = {};
+    return $attrs unless defined $bre_ids;
+    $bre_ids = [$bre_ids] unless ref $bre_ids;
+
+    my $mra = $e->json_query({
+        select => {
+            mra => [
+                {
+                    column => 'id',
+                    alias => 'bre'
+                }, {
+                    column => 'attrs',
+                    transform => 'each',
+                    result_field => 'key',
+                    alias => 'key'
+                },{
+                    column => 'attrs',
+                    transform => 'each',
+                    result_field => 'value',
+                    alias => 'value'
+                }
+            ]
+        },
+        from => 'mra',
+        where => {id => $bre_ids}
+    });
+
+    return $attrs unless $mra;
+
+    $ccvm_cache = $ccvm_cache || $e->search_config_coded_value_map({id => {'!=' => undef}});
+
+    for my $id (@$bre_ids) {
+        $attrs->{$id} = {};
+        for my $mra (grep { $_->{bre} eq $id } @$mra) {
+            my $ctype = $mra->{key};
+            my $code = $mra->{value};
+            $attrs->{$id}->{$ctype} = {code => $code};
+            if($code) {
+                my ($ccvm) = grep { $_->ctype eq $ctype and $_->code eq $code } @$ccvm_cache;
+                $attrs->{$id}->{$ctype}->{label} = $ccvm->value if $ccvm;
+            }
+        }
+    }
+
+    return $attrs;
+}
+
 1;
 
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
new file mode 100644 (file)
index 0000000..8a8bc70
--- /dev/null
@@ -0,0 +1,299 @@
+package OpenILS::WWW::EGCatLoader;
+use strict; use warnings;
+use XML::LibXML;
+use URI::Escape;
+use Digest::MD5 qw(md5_hex);
+use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
+use OpenSRF::AppSession;
+use OpenSRF::EX qw/:try/;
+use OpenSRF::Utils qw/:datetime/;
+use OpenSRF::Utils::JSON;
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenILS::Application::AppUtils;
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use OpenILS::Utils::Fieldmapper;
+use DateTime::Format::ISO8601;
+use CGI qw(:all -utf8);
+
+# EGCatLoader sub-modules 
+use OpenILS::WWW::EGCatLoader::Util;
+use OpenILS::WWW::EGCatLoader::Account;
+use OpenILS::WWW::EGCatLoader::Search;
+use OpenILS::WWW::EGCatLoader::Record;
+use OpenILS::WWW::EGCatLoader::Container;
+
+my $U = 'OpenILS::Application::AppUtils';
+
+use constant COOKIE_SES => 'ses';
+
+sub new {
+    my($class, $apache, $ctx) = @_;
+
+    my $self = bless({}, ref($class) || $class);
+
+    $self->apache($apache);
+    $self->ctx($ctx);
+    $self->cgi(new CGI);
+
+    OpenILS::Utils::CStoreEditor->init; # just in case
+    $self->editor(new_editor());
+
+    return $self;
+}
+
+
+# current Apache2::RequestRec;
+sub apache {
+    my($self, $apache) = @_;
+    $self->{apache} = $apache if $apache;
+    return $self->{apache};
+}
+
+# runtime / template context
+sub ctx {
+    my($self, $ctx) = @_;
+    $self->{ctx} = $ctx if $ctx;
+    return $self->{ctx};
+}
+
+# cstore editor
+sub editor {
+    my($self, $editor) = @_;
+    $self->{editor} = $editor if $editor;
+    return $self->{editor};
+}
+
+# CGI handle
+sub cgi {
+    my($self, $cgi) = @_;
+    $self->{cgi} = $cgi if $cgi;
+    return $self->{cgi};
+}
+
+
+# -----------------------------------------------------------------------------
+# Perform initial setup, load common data, then load page data
+# -----------------------------------------------------------------------------
+sub load {
+    my $self = shift;
+
+    $self->init_ro_object_cache;
+
+    my $stat = $self->load_common;
+    return $stat unless $stat == Apache2::Const::OK;
+
+    my $path = $self->apache->path_info;
+
+    (undef, $self->ctx->{mylist}) = $self->fetch_mylist unless
+        $path =~ /opac\/my(opac\/lists|list)/;
+
+    return $self->load_simple("home") if $path =~ m|opac/home|;
+    return $self->load_simple("advanced") if $path =~ m|opac/advanced|;
+    return $self->load_rresults if $path =~ m|opac/results|;
+    return $self->load_record if $path =~ m|opac/record|;
+
+    return $self->load_mylist_add if $path =~ m|opac/mylist/add|;
+    return $self->load_mylist_move if $path =~ m|opac/mylist/move|;
+    return $self->load_mylist if $path =~ m|opac/mylist|;
+    return $self->load_cache_clear if $path =~ m|opac/cache/clear|;
+
+    # ----------------------------------------------------------------
+    # Logout and login require SSL
+    # ----------------------------------------------------------------
+    if($path =~ m|opac/login|) {
+        return $self->redirect_ssl unless $self->cgi->https;
+        return $self->load_login;
+    }
+
+    if($path =~ m|opac/logout|) {
+        #return Apache2::Const::FORBIDDEN unless $self->cgi->https; 
+        $self->apache->log->warn("catloader: logout called in non-secure context from " . 
+            ($self->ctx->{referer} || '<no referer>')) unless $self->cgi->https;
+        return $self->load_logout;
+    }
+
+    # ----------------------------------------------------------------
+    #  Everything below here requires SSL + authentication
+    # ----------------------------------------------------------------
+    return $self->redirect_auth
+        unless $self->cgi->https and $self->editor->requestor;
+
+    return $self->load_place_hold if $path =~ m|opac/place_hold|;
+    return $self->load_myopac_holds if $path =~ m|opac/myopac/holds|;
+    return $self->load_myopac_circs if $path =~ m|opac/myopac/circs|;
+    return $self->load_myopac_payment_form if $path =~ m|opac/myopac/main_payment_form|;
+    return $self->load_myopac_payments if $path =~ m|opac/myopac/main_payments|;
+    return $self->load_myopac_main if $path =~ m|opac/myopac/main|;
+    return $self->load_myopac_update_email if $path =~ m|opac/myopac/update_email|;
+    return $self->load_myopac_update_password if $path =~ m|opac/myopac/update_password|;
+    return $self->load_myopac_update_username if $path =~ m|opac/myopac/update_username|;
+    return $self->load_myopac_bookbags if $path =~ m|opac/myopac/lists|;
+    return $self->load_myopac_bookbag_update if $path =~ m|opac/myopac/list/update|;
+    return $self->load_myopac_circ_history if $path =~ m|opac/myopac/circ_history|;
+    return $self->load_myopac_hold_history if $path =~ m|opac/myopac/hold_history|;
+    return $self->load_myopac_prefs_notify if $path =~ m|opac/myopac/prefs_notify|;
+    return $self->load_myopac_prefs_settings if $path =~ m|opac/myopac/prefs_settings|;
+    return $self->load_myopac_prefs if $path =~ m|opac/myopac/prefs|;
+
+    return Apache2::Const::OK;
+}
+
+
+# -----------------------------------------------------------------------------
+# Redirect to SSL equivalent of a given page
+# -----------------------------------------------------------------------------
+sub redirect_ssl {
+    my $self = shift;
+    my $new_page = sprintf('https://%s%s', $self->apache->hostname, $self->apache->unparsed_uri);
+    return $self->generic_redirect($new_page);
+}
+
+# -----------------------------------------------------------------------------
+# If an authnticated resource is requested w/o auth, redirect to the login page,
+# then return to the originally requrested resource upon successful login.
+# -----------------------------------------------------------------------------
+sub redirect_auth {
+    my $self = shift;
+    my $login_page = sprintf('https://%s%s/login', $self->apache->hostname, $self->ctx->{opac_root});
+    my $redirect_to = uri_escape($self->apache->unparsed_uri);
+    return $self->generic_redirect("$login_page?redirect_to=$redirect_to");
+}
+
+# -----------------------------------------------------------------------------
+# Fall-through for loading a basic page
+# -----------------------------------------------------------------------------
+sub load_simple {
+    my ($self, $page) = @_;
+    $self->ctx->{page} = $page;
+    return Apache2::Const::OK;
+}
+
+# -----------------------------------------------------------------------------
+# Tests to see if the user is authenticated and sets some common context values
+# -----------------------------------------------------------------------------
+sub load_common {
+    my $self = shift;
+
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+
+    $ctx->{referer} = $self->cgi->referer;
+    $ctx->{path_info} = $self->cgi->path_info;
+    $ctx->{full_path} = $ctx->{base_path} . $self->cgi->path_info;
+    $ctx->{unparsed_uri} = $self->apache->unparsed_uri;
+    $ctx->{opac_root} = $ctx->{base_path} . "/opac"; # absolute base url
+    $ctx->{is_staff} = ($self->apache->headers_in->get('User-Agent') =~ /oils_xulrunner/);
+
+    # capture some commonly accessed pages
+    $ctx->{home_page} = 'http://' . $self->apache->hostname . $self->ctx->{opac_root} . "/home";
+    $ctx->{logout_page} = 'https://' . $self->apache->hostname . $self->ctx->{opac_root} . "/logout";
+
+    if($e->authtoken($self->cgi->cookie(COOKIE_SES))) {
+
+        if($e->checkauth) {
+
+            $ctx->{authtoken} = $e->authtoken;
+            $ctx->{authtime} = $e->authtime;
+            $ctx->{user} = $e->requestor;
+
+            $ctx->{user_stats} = $U->simplereq(
+                'open-ils.actor', 
+                'open-ils.actor.user.opac.vital_stats', 
+                $e->authtoken, $e->requestor->id);
+
+        } else {
+
+            # if we encounter a stale authtoken, call load_logout 
+            # to clean up the cookie, then redirect the user to the
+            # originally requested page
+            return $self->load_logout($self->apache->unparsed_uri);
+        }
+    }
+
+    return Apache2::Const::OK;
+}
+
+
+# -----------------------------------------------------------------------------
+# Log in and redirect to the redirect_to URL (or home)
+# -----------------------------------------------------------------------------
+sub load_login {
+    my $self = shift;
+    my $cgi = $self->cgi;
+    my $ctx = $self->ctx;
+
+    $ctx->{page} = 'login';
+
+    my $username = $cgi->param('username');
+    my $password = $cgi->param('password');
+    my $org_unit = $cgi->param('loc') || $ctx->{aou_tree}->()->id;
+    my $persist = $cgi->param('persist');
+
+    # initial log form only
+    return Apache2::Const::OK unless $username and $password;
+
+       my $seed = $U->simplereq(
+        'open-ils.auth', 
+               'open-ils.auth.authenticate.init', $username);
+
+    my $args = {       
+        barcode => $username, 
+        password => md5_hex($seed . md5_hex($password)), 
+        type => ($persist) ? 'persist' : 'opac' 
+    };
+
+    my $bc_regex = $ctx->{get_org_setting}->($org_unit, 'opac.barcode_regex');
+
+    $args->{username} = delete $args->{barcode} 
+        if $bc_regex and !($username =~ /$bc_regex/);
+
+       my $response = $U->simplereq(
+        'open-ils.auth', 'open-ils.auth.authenticate.complete', $args);
+
+    if($U->event_code($response)) { 
+        # login failed, report the reason to the template
+        $ctx->{login_failed_event} = $response;
+        return Apache2::Const::OK;
+    }
+
+    # login succeeded, redirect as necessary
+
+    my $acct = $self->apache->unparsed_uri;
+    $acct =~ s|/login|/myopac/main|;
+
+    return $self->generic_redirect(
+        $cgi->param('redirect_to') || $acct,
+        $cgi->cookie(
+            -name => COOKIE_SES,
+            -path => '/',
+            -secure => 1,
+            -value => $response->{payload}->{authtoken},
+            -expires => ($persist) ? CORE::time + $response->{payload}->{authtime} : undef
+        )
+    );
+}
+
+# -----------------------------------------------------------------------------
+# Log out and redirect to the home page
+# -----------------------------------------------------------------------------
+sub load_logout {
+    my $self = shift;
+    my $redirect_to = shift;
+
+    # If the user was adding anyting to an anonymous cache 
+    # while logged in, go ahead and clear it out.
+    $self->clear_anon_cache;
+
+    return $self->generic_redirect(
+        $redirect_to || $self->ctx->{home_page},
+        $self->cgi->cookie(
+            -name => COOKIE_SES,
+            -path => '/',
+            -value => '',
+            -expires => '-1h'
+        )
+    );
+}
+
+1;
+
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
new file mode 100644 (file)
index 0000000..e9da422
--- /dev/null
@@ -0,0 +1,930 @@
+package OpenILS::WWW::EGCatLoader;
+use strict; use warnings;
+use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use OpenILS::Utils::Fieldmapper;
+use OpenILS::Application::AppUtils;
+use OpenSRF::Utils::JSON;
+my $U = 'OpenILS::Application::AppUtils';
+
+sub load_extended_user_info {
+    my $self = shift;
+
+    $self->ctx->{user} = $self->editor->retrieve_actor_user([
+        $self->ctx->{user}->id,
+        {
+            flesh => 1,
+            flesh_fields => {
+                au => [qw/card home_ou addresses ident_type billing_address/]
+                # ...
+            }
+        }
+    ]) or return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR;
+
+    return;
+}
+
+# context additions: 
+#   user : au object, fleshed
+sub load_myopac_prefs {
+    my $self = shift;
+    return $self->load_extended_user_info || Apache2::Const::OK;
+}
+
+sub load_myopac_prefs_notify {
+    my $self = shift;
+    my $e = $self->editor;
+
+    my $user_prefs = $self->fetch_optin_prefs;
+    $user_prefs = $self->update_optin_prefs($user_prefs)
+        if $self->cgi->request_method eq 'POST';
+
+    $self->ctx->{opt_in_settings} = $user_prefs; 
+
+    return Apache2::Const::OK;
+}
+
+sub fetch_optin_prefs {
+    my $self = shift;
+    my $e = $self->editor;
+
+    # fetch all of the opt-in settings the user has access to
+    # XXX: user's should in theory have options to opt-in to notices
+    # for remote locations, but that opens the door for a large
+    # set of generally un-used opt-ins.. needs discussion
+    my $opt_ins =  $U->simplereq(
+        'open-ils.actor',
+        'open-ils.actor.event_def.opt_in.settings.atomic',
+        $e->authtoken, $e->requestor->home_ou);
+
+    # fetch user setting values for each of the opt-in settings
+    my $user_set = $U->simplereq(
+        'open-ils.actor',
+        'open-ils.actor.patron.settings.retrieve',
+        $e->authtoken, 
+        $e->requestor->id, 
+        [map {$_->name} @$opt_ins]
+    );
+
+    return [map { {cust => $_, value => $user_set->{$_->name} } } @$opt_ins];
+}
+
+sub update_optin_prefs {
+    my $self = shift;
+    my $user_prefs = shift;
+    my $e = $self->editor;
+    my @settings = $self->cgi->param('setting');
+    my %newsets;
+
+    # apply now-true settings
+    for my $applied (@settings) {
+        # see if setting is already applied to this user
+        next if grep { $_->{cust}->name eq $applied and $_->{value} } @$user_prefs;
+        $newsets{$applied} = OpenSRF::Utils::JSON->true;
+    }
+
+    # remove now-false settings
+    for my $pref (grep { $_->{value} } @$user_prefs) {
+        $newsets{$pref->{cust}->name} = undef 
+            unless grep { $_ eq $pref->{cust}->name } @settings;
+    }
+
+    $U->simplereq(
+        'open-ils.actor',
+        'open-ils.actor.patron.settings.update',
+        $e->authtoken, $e->requestor->id, \%newsets);
+
+    # update the local prefs to match reality
+    for my $pref (@$user_prefs) {
+        $pref->{value} = $newsets{$pref->{cust}->name} 
+            if exists $newsets{$pref->{cust}->name};
+    }
+
+    return $user_prefs;
+}
+
+sub load_myopac_prefs_settings {
+    my $self = shift;
+    return $self->load_extended_user_info || Apache2::Const::OK;
+}
+
+sub fetch_user_holds {
+    my $self = shift;
+    my $hold_ids = shift;
+    my $ids_only = shift;
+    my $flesh = shift;
+    my $available = shift;
+    my $limit = shift;
+    my $offset = shift;
+
+    my $e = $self->editor;
+
+    my $circ = OpenSRF::AppSession->create('open-ils.circ');
+
+    if(!$hold_ids) {
+
+        $hold_ids = $circ->request(
+            'open-ils.circ.holds.id_list.retrieve.authoritative', 
+            $e->authtoken, 
+            $e->requestor->id
+        )->gather(1);
+    
+        $hold_ids = [ grep { defined $_ } @$hold_ids[$offset..($offset + $limit - 1)] ] if $limit or $offset;
+    }
+
+
+    return $hold_ids if $ids_only or @$hold_ids == 0;
+
+    my $args = {
+        suppress_notices => 1,
+        suppress_transits => 1,
+        suppress_mvr => 1,
+        suppress_patron_details => 1,
+        include_bre => $flesh ? 1 : 0
+    };
+
+    # ----------------------------------------------------------------
+    # Collect holds in batches of $batch_size for faster retrieval
+
+    my $batch_size = 8;
+    my $batch_idx = 0;
+    my $mk_req_batch = sub {
+        my @ses;
+        my $top_idx = $batch_idx + $batch_size;
+        while($batch_idx < $top_idx) {
+            my $hold_id = $hold_ids->[$batch_idx++];
+            last unless $hold_id;
+            my $ses = OpenSRF::AppSession->create('open-ils.circ');
+            my $req = $ses->request(
+                'open-ils.circ.hold.details.retrieve', 
+                $e->authtoken, $hold_id, $args);
+            push(@ses, {ses => $ses, req => $req});
+        }
+        return @ses;
+    };
+
+    my $first = 1;
+    my(@collected, @holds, @ses);
+
+    while(1) {
+        @ses = $mk_req_batch->() if $first;
+        last if $first and not @ses;
+
+        if(@collected) {
+            # If desired by the caller, filter any holds that are not available.
+            if ($available) {
+                @collected = grep { $_->{hold}->{status} == 4 } @collected;
+            }
+            while(my $blob = pop(@collected)) {
+                $blob->{marc_xml} = XML::LibXML->new->parse_string($blob->{hold}->{bre}->marc) if $flesh;
+                push(@holds, $blob);
+            }
+        }
+
+        for my $req_data (@ses) {
+            push(@collected, {hold => $req_data->{req}->gather(1)});
+            $req_data->{ses}->kill_me;
+        }
+
+        @ses = $mk_req_batch->();
+        last unless @collected or @ses;
+        $first = 0;
+    }
+
+    # put the holds back into the original server sort order
+    my @sorted;
+    for my $id (@$hold_ids) {
+        push @sorted, grep { $_->{hold}->{hold}->id == $id } @holds;
+    }
+
+    return \@sorted;
+}
+
+sub handle_hold_update {
+    my $self = shift;
+    my $action = shift;
+    my $e = $self->editor;
+    my $url;
+
+    my @hold_ids = $self->cgi->param('hold_id'); # for non-_all actions
+    @hold_ids = @{$self->fetch_user_holds(undef, 1)} if $action =~ /_all/;
+
+    my $circ = OpenSRF::AppSession->create('open-ils.circ');
+
+    if($action =~ /cancel/) {
+
+        for my $hold_id (@hold_ids) {
+            my $resp = $circ->request(
+                'open-ils.circ.hold.cancel', $e->authtoken, $hold_id, 6 )->gather(1); # 6 == patron-cancelled-via-opac
+        }
+
+    } elsif ($action =~ /activate|suspend/) {
+        
+        my $vlist = [];
+        for my $hold_id (@hold_ids) {
+            my $vals = {id => $hold_id};
+
+            if($action =~ /activate/) {
+                $vals->{frozen} = 'f';
+                $vals->{thaw_date} = undef;
+
+            } elsif($action =~ /suspend/) {
+                $vals->{frozen} = 't';
+                # $vals->{thaw_date} = TODO;
+            }
+            push(@$vlist, $vals);
+        }
+
+        $circ->request('open-ils.circ.hold.update.batch.atomic', $e->authtoken, undef, $vlist)->gather(1);
+    } elsif ($action eq 'edit') {
+
+        my @vals = map {
+            my $val = {"id" => $_};
+            $val->{"frozen"} = $self->cgi->param("frozen");
+            $val->{"pickup_lib"} = $self->cgi->param("pickup_lib");
+
+            for my $field (qw/expire_time thaw_date/) {
+                # XXX TODO make this support other date formats, not just
+                # MM/DD/YYYY.
+                next unless $self->cgi->param($field) =~
+                    m:^(\d{2})/(\d{2})/(\d{4})$:;
+                $val->{$field} = "$3-$1-$2";
+            }
+            $val;
+        } @hold_ids;
+
+        $circ->request(
+            'open-ils.circ.hold.update.batch.atomic',
+            $e->authtoken, undef, \@vals
+        )->gather(1);   # LFW XXX test for failure
+        $url = 'https://' . $self->apache->hostname . $self->ctx->{opac_root} . '/myopac/holds';
+    }
+
+    $circ->kill_me;
+    return defined($url) ? $self->generic_redirect($url) : undef;
+}
+
+sub load_myopac_holds {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+    
+
+    my $limit = $self->cgi->param('limit') || 0;
+    my $offset = $self->cgi->param('offset') || 0;
+    my $action = $self->cgi->param('action') || '';
+    my $available = int($self->cgi->param('available') || 0);
+
+    my $hold_handle_result;
+    $hold_handle_result = $self->handle_hold_update($action) if $action;
+
+    $ctx->{holds} = $self->fetch_user_holds(undef, 0, 1, $available, $limit, $offset);
+
+    return defined($hold_handle_result) ? $hold_handle_result : Apache2::Const::OK;
+}
+
+sub load_place_hold {
+    my $self = shift;
+    my $ctx = $self->ctx;
+    my $e = $self->editor;
+    my $cgi = $self->cgi;
+    $self->ctx->{page} = 'place_hold';
+
+    $ctx->{hold_target} = $cgi->param('hold_target');
+    $ctx->{hold_type} = $cgi->param('hold_type');
+    $ctx->{default_pickup_lib} = $e->requestor->home_ou; # XXX staff
+
+    if ($ctx->{hold_type} eq 'T') {
+        $ctx->{record} = $e->retrieve_biblio_record_entry($ctx->{hold_target});
+    } elsif ($ctx->{hold_type} eq 'I') {
+        my $iss = $e->retrieve_serial_issuance([
+            $ctx->{hold_target}, {
+                "flesh" => 2,
+                "flesh_fields" => {
+                    "siss" => ["subscription"], "ssub" => ["record_entry"]
+                }
+            }
+        ]);
+        $ctx->{record} = $iss->subscription->record_entry;
+    }
+    # ...
+
+    $ctx->{marc_xml} = XML::LibXML->new->parse_string($ctx->{record}->marc);
+
+    if(my $pickup_lib = $cgi->param('pickup_lib')) {
+
+        my $args = {
+            patronid => $e->requestor->id,
+            titleid => $ctx->{hold_target}, # XXX
+            pickup_lib => $pickup_lib,
+            depth => 0, # XXX
+        };
+
+        my $allowed = $U->simplereq(
+            'open-ils.circ',
+            'open-ils.circ.title_hold.is_possible',
+            $e->authtoken, $args
+        );
+
+        if($allowed->{success} == 1) {
+            my $hold = Fieldmapper::action::hold_request->new;
+
+            $hold->pickup_lib($pickup_lib);
+            $hold->requestor($e->requestor->id);
+            $hold->usr($e->requestor->id); # XXX staff
+            $hold->target($ctx->{hold_target});
+            $hold->hold_type($ctx->{hold_type});
+            # frozen, expired, etc..
+
+            my $stat = $U->simplereq(
+                'open-ils.circ',
+                'open-ils.circ.holds.create',
+                $e->authtoken, $hold
+            );
+
+            if($stat and $stat > 0) {
+                # if successful, return the user to the requesting page
+                $self->apache->log->info("Redirecting back to " . $cgi->param('redirect_to'));
+                return $self->generic_redirect;
+
+            } else {
+                $ctx->{hold_failed} = 1;
+            }
+        } else { # hold *check* failed
+            $ctx->{hold_failed} = 1; # XXX process the events, etc
+            $ctx->{hold_failed_event} = $allowed->{last_event};
+        }
+
+        # hold permit failed
+        $logger->info('hold permit result ' . OpenSRF::Utils::JSON->perl2JSON($allowed));
+    }
+
+    return Apache2::Const::OK;
+}
+
+
+sub fetch_user_circs {
+    my $self = shift;
+    my $flesh = shift; # flesh bib data, etc.
+    my $circ_ids = shift;
+    my $limit = shift;
+    my $offset = shift;
+
+    my $e = $self->editor;
+
+    my @circ_ids;
+
+    if($circ_ids) {
+        @circ_ids = @$circ_ids;
+
+    } else {
+
+        my $circ_data = $U->simplereq(
+            'open-ils.actor', 
+            'open-ils.actor.user.checked_out',
+            $e->authtoken, 
+            $e->requestor->id
+        );
+
+        @circ_ids =  ( @{$circ_data->{overdue}}, @{$circ_data->{out}} );
+
+        if($limit or $offset) {
+            @circ_ids = grep { defined $_ } @circ_ids[0..($offset + $limit - 1)];
+        }
+    }
+
+    return [] unless @circ_ids;
+
+    my $cstore = OpenSRF::AppSession->create('open-ils.cstore');
+
+    my $qflesh = {
+        flesh => 3,
+        flesh_fields => {
+            circ => ['target_copy'],
+            acp => ['call_number'],
+            acn => ['record']
+        }
+    };
+
+    $e->xact_begin;
+    my $circs = $e->search_action_circulation(
+        [{id => \@circ_ids}, ($flesh) ? $qflesh : {}], {substream => 1});
+
+    my @circs;
+    for my $circ (@$circs) {
+        push(@circs, {
+            circ => $circ, 
+            marc_xml => ($flesh and $circ->target_copy->call_number->id != -1) ? 
+                XML::LibXML->new->parse_string($circ->target_copy->call_number->record->marc) : 
+                undef  # pre-cat copy, use the dummy title/author instead
+        });
+    }
+    $e->xact_rollback;
+
+    # make sure the final list is in the correct order
+    my @sorted_circs;
+    for my $id (@circ_ids) {
+        push(
+            @sorted_circs,
+            (grep { $_->{circ}->id == $id } @circs)
+        );
+    }
+
+    return \@sorted_circs;
+}
+
+
+sub handle_circ_renew {
+    my $self = shift;
+    my $action = shift;
+    my $ctx = $self->ctx;
+
+    my @renew_ids = $self->cgi->param('circ');
+
+    my $circs = $self->fetch_user_circs(0, ($action eq 'renew') ? [@renew_ids] : undef);
+
+    # TODO: fire off renewal calls in batches to speed things up
+    my @responses;
+    for my $circ (@$circs) {
+
+        my $evt = $U->simplereq(
+            'open-ils.circ', 
+            'open-ils.circ.renew',
+            $self->editor->authtoken,
+            {
+                patron_id => $self->editor->requestor->id,
+                copy_id => $circ->{circ}->target_copy,
+                opac_renewal => 1
+            }
+        );
+
+        # TODO return these, then insert them into the circ data 
+        # blob that is shoved into the template for each circ
+        # so the template won't have to match them
+        push(@responses, {copy => $circ->{circ}->target_copy, evt => $evt});
+    }
+
+    return @responses;
+}
+
+
+sub load_myopac_circs {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+
+    $ctx->{circs} = [];
+    my $limit = $self->cgi->param('limit') || 0; # 0 == unlimited
+    my $offset = $self->cgi->param('offset') || 0;
+    my $action = $self->cgi->param('action') || '';
+
+    # perform the renewal first if necessary
+    my @results = $self->handle_circ_renew($action) if $action =~ /renew/;
+
+    $ctx->{circs} = $self->fetch_user_circs(1, undef, $limit, $offset);
+
+    my $success_renewals = 0;
+    my $failed_renewals = 0;
+    for my $data (@{$ctx->{circs}}) {
+        my ($resp) = grep { $_->{copy} == $data->{circ}->target_copy->id } @results;
+
+        if($resp) {
+            my $evt = ref($resp->{evt}) eq 'ARRAY' ? $resp->{evt}->[0] : $resp->{evt};
+            $data->{renewal_response} = $evt;
+            $success_renewals++ if $evt->{textcode} eq 'SUCCESS';
+            $failed_renewals++ if $evt->{textcode} ne 'SUCCESS';
+        }
+    }
+
+    $ctx->{success_renewals} = $success_renewals;
+    $ctx->{failed_renewals} = $failed_renewals;
+
+    return Apache2::Const::OK;
+}
+
+sub load_myopac_circ_history {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+    my $limit = $self->cgi->param('limit') || 15;
+    my $offset = $self->cgi->param('offset') || 0;
+
+    $ctx->{circ_history_limit} = $limit;
+    $ctx->{circ_history_offset} = $offset;
+
+    my $circs = $e->json_query({
+        from => ['action.usr_visible_circs', $e->requestor->id],
+        #limit => $limit || 25,
+        #offset => $offset || 0,
+    });
+
+    # XXX: order-by in the json_query above appears to do nothing, so in-query 
+    # paging is not reallly an option.  do the sorting/paging here
+
+    # sort newest to oldest
+    $circs = [ sort { $b->{xact_start} cmp $a->{xact_start} } @$circs ];
+    my @ids = map { $_->{id} } @$circs;
+
+    # find the selected page and trim cruft
+    @ids = @ids[$offset..($offset + $limit - 1)] if $limit;
+    @ids = grep { defined $_ } @ids;
+
+    $ctx->{circs} = $self->fetch_user_circs(1, \@ids);
+    #$ctx->{circs} = $self->fetch_user_circs(1, [map { $_->{id} } @$circs], $limit, $offset);
+
+    return Apache2::Const::OK;
+}
+
+# TODO: action.usr_visible_holds does not return cancelled holds.  Should it?
+sub load_myopac_hold_history {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+    my $limit = $self->cgi->param('limit') || 15;
+    my $offset = $self->cgi->param('offset') || 0;
+    $ctx->{hold_history_limit} = $limit;
+    $ctx->{hold_history_offset} = $offset;
+
+
+    my $holds = $e->json_query({
+        from => ['action.usr_visible_holds', $e->requestor->id],
+        limit => $limit || 25,
+        offset => $offset || 0
+    });
+
+    $ctx->{holds} = $self->fetch_user_holds([map { $_->{id} } @$holds], 0, 1, 0, $limit, $offset);
+
+    return Apache2::Const::OK;
+}
+
+sub load_myopac_payment_form {
+    my $self = shift;
+    my $r;
+
+    $r = $self->load_fines(undef, undef, [$self->cgi->param('xact')]) and return $r;
+
+    # total selected fines
+    foreach (
+        @{$self->ctx->{"fines"}->{"circulation"}},
+        @{$self->ctx->{"fines"}->{"grocery"}}
+    ) {
+    }
+
+    $r = $self->load_extended_user_info and return $r;
+
+    return Apache2::Const::OK;
+}
+
+# TODO: add other filter options as params/configs/etc.
+sub load_myopac_payments {
+    my $self = shift;
+    my $limit = $self->cgi->param('limit') || 20;
+    my $offset = $self->cgi->param('offset') || 0;
+    my $e = $self->editor;
+
+    $self->ctx->{payment_history_limit} = $limit;
+    $self->ctx->{payment_history_offset} = $offset;
+
+    my $args = {};
+    $args->{limit} = $limit if $limit;
+    $args->{offset} = $offset if $offset;
+
+    $self->ctx->{payments} = $U->simplereq(
+        'open-ils.actor',
+        'open-ils.actor.user.payments.retrieve.atomic',
+        $e->authtoken, $e->requestor->id, $args);
+
+    return Apache2::Const::OK;
+}
+
+sub load_fines {
+    my ($self, $limit, $offset, $id_list) = @_;
+
+    # XXX TODO: check for failure after various network calls
+
+    $self->ctx->{"fines"} = {
+        "circulation" => [],
+        "grocery" => [],
+        "total_paid" => 0,
+        "total_owed" => 0,
+        "balance_owed" => 0
+    };
+
+    my $cstore = OpenSRF::AppSession->create('open-ils.cstore');
+
+    # TODO: This should really be a ML call, but the existing calls 
+    # return an excessive amount of data and don't offer streaming
+
+    my %paging = ($limit or $offset) ? (limit => $limit, offset => $offset) : ();
+
+    my $req = $cstore->request(
+        'open-ils.cstore.direct.money.open_billable_transaction_summary.search',
+        {
+            usr => $self->editor->requestor->id,
+            balance_owed => {'!=' => 0},
+            ($id_list && @$id_list ? ("id" => $id_list) : ()),
+        },
+        {
+            flesh => 4,
+            flesh_fields => {
+                mobts => [qw/grocery circulation reservation/],
+                bresv => ['target_resource_type'],
+                brt => ['record'],
+                mg => ['billings'],
+                mb => ['btype'],
+                circ => ['target_copy'],
+                acp => ['call_number'],
+                acn => ['record']
+            },
+            order_by => { mobts => 'xact_start' },
+            %paging
+        }
+    );
+
+    my @total_keys = qw/total_paid total_owed balance_owed/;
+    $self->ctx->{"fines"}->{@total_keys} = (0, 0, 0);
+
+    while(my $resp = $req->recv) {
+        my $mobts = $resp->content;
+        my $circ = $mobts->circulation;
+
+        my $last_billing;
+        if($mobts->grocery) {
+            my @billings = sort { $a->billing_ts cmp $b->billing_ts } @{$mobts->grocery->billings};
+            $last_billing = pop(@billings);
+        }
+
+        # XXX TODO confirm that the following, and the later division by 100.0
+        # to get a floating point representation once again, is sufficiently
+        # "money-safe" math.
+        $self->ctx->{"fines"}->{$_} += int($mobts->$_ * 100) for (@total_keys);
+
+        my $marc_xml = undef;
+        if ($mobts->xact_type eq 'reservation' and
+            $mobts->reservation->target_resource_type->record) {
+            $marc_xml = XML::LibXML->new->parse_string(
+                $mobts->reservation->target_resource_type->record->marc
+            );
+        } elsif ($mobts->xact_type eq 'circulation' and
+            $circ->target_copy->call_number->id != -1) {
+            $marc_xml = XML::LibXML->new->parse_string(
+                $circ->target_copy->call_number->record->marc
+            );
+        }
+
+        push(
+            @{$self->ctx->{"fines"}->{$mobts->grocery ? "grocery" : "circulation"}},
+            {
+                xact => $mobts,
+                last_grocery_billing => $last_billing,
+                marc_xml => $marc_xml
+            } 
+        );
+    }
+
+    $self->ctx->{"fines"}->{$_} /= 100.0 for (@total_keys);
+    return;
+}
+
+sub load_myopac_main {
+    my $self = shift;
+    my $limit = $self->cgi->param('limit') || 0;
+    my $offset = $self->cgi->param('offset') || 0;
+
+    return $self->load_fines($limit, $offset) || Apache2::Const::OK;
+}
+
+sub load_myopac_update_email {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+    my $email = $self->cgi->param('email') || '';
+
+    return Apache2::Const::OK 
+        unless $self->cgi->request_method eq 'POST';
+
+    unless($email =~ /.+\@.+\..+/) { # TODO better regex?
+        $ctx->{invalid_email} = $email;
+        return Apache2::Const::OK;
+    }
+
+    my $stat = $U->simplereq(
+        'open-ils.actor', 
+        'open-ils.actor.user.email.update', 
+        $e->authtoken, $email);
+
+    my $url = $self->apache->unparsed_uri;
+    $url =~ s/update_email/prefs/;
+
+    return $self->generic_redirect($url);
+}
+
+sub load_myopac_update_username {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+    my $username = $self->cgi->param('username') || '';
+
+    return Apache2::Const::OK 
+        unless $self->cgi->request_method eq 'POST';
+
+    unless($username and $username !~ /\s/) { # any other username restrictions?
+        $ctx->{invalid_username} = $username;
+        return Apache2::Const::OK;
+    }
+
+    if($username ne $e->requestor->usrname) {
+
+        my $evt = $U->simplereq(
+            'open-ils.actor', 
+            'open-ils.actor.user.username.update', 
+            $e->authtoken, $username);
+
+        if($U->event_equals($evt, 'USERNAME_EXISTS')) {
+            $ctx->{username_exists} = $username;
+            return Apache2::Const::OK;
+        }
+    }
+
+    my $url = $self->apache->unparsed_uri;
+    $url =~ s/update_username/prefs/;
+
+    return $self->generic_redirect($url);
+}
+
+sub load_myopac_update_password {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+
+    return Apache2::Const::OK 
+        unless $self->cgi->request_method eq 'POST';
+
+    my $current_pw = $self->cgi->param('current_pw') || '';
+    my $new_pw = $self->cgi->param('new_pw') || '';
+    my $new_pw2 = $self->cgi->param('new_pw2') || '';
+
+    unless($new_pw eq $new_pw2) {
+        $ctx->{password_nomatch} = 1;
+        return Apache2::Const::OK;
+    }
+
+    my $pw_regex = $ctx->{get_org_setting}->($e->requestor->home_ou, 'global.password_regex');
+
+    if($pw_regex and $new_pw !~ /$pw_regex/) {
+        $ctx->{password_invalid} = 1;
+        return Apache2::Const::OK;
+    }
+
+    my $evt = $U->simplereq(
+        'open-ils.actor', 
+        'open-ils.actor.user.password.update', 
+        $e->authtoken, $new_pw, $current_pw);
+
+
+    if($U->event_equals($evt, 'INCORRECT_PASSWORD')) {
+        $ctx->{password_incorrect} = 1;
+        return Apache2::Const::OK;
+    }
+
+    my $url = $self->apache->unparsed_uri;
+    $url =~ s/update_password/prefs/;
+
+    return $self->generic_redirect($url);
+}
+
+sub load_myopac_bookbags {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+
+    $e->xact_begin; # replication...
+
+    my $rv = $self->load_mylist;
+    unless($rv eq Apache2::Const::OK) {
+        $e->rollback;
+        return $rv;
+    }
+
+    my $args = {
+        order_by => {cbreb => 'name'},
+        limit => $self->cgi->param('limit') || 10,
+        offset => $self->cgi->param('offset') || 0
+    };
+
+    $ctx->{bookbags} = $e->search_container_biblio_record_entry_bucket([
+        {owner => $self->editor->requestor->id, btype => 'bookbag'},
+        # XXX what to do about the possibility of really large bookbags here?
+        {"flesh" => 1, "flesh_fields" => {"cbreb" => ["items"]}, %$args}
+    ]);
+
+    if(!$ctx->{bookbags}) {
+        $e->rollback;
+        return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR;
+    }
+    
+    # get unique record IDs
+    my %rec_ids = ();
+    foreach my $bbag (@{$ctx->{bookbags}}) {
+        foreach my $rec_id (
+            map { $_->target_biblio_record_entry } @{$bbag->items}
+        ) {
+            $rec_ids{$rec_id} = 1;
+        }
+    }
+
+    $ctx->{bookbags_marc_xml} = $self->fetch_marc_xml_by_id([keys %rec_ids]);
+
+    $e->rollback;
+    return Apache2::Const::OK;
+}
+
+
+# actions are create, delete, show, hide, rename, add_rec, delete_item
+# CGI is action, list=list_id, add_rec/record=bre_id, del_item=bucket_item_id, name=new_bucket_name
+sub load_myopac_bookbag_update {
+    my ($self, $action, $list_id) = @_;
+    my $e = $self->editor;
+    my $cgi = $self->cgi;
+
+    $action ||= $cgi->param('action');
+    $list_id ||= $cgi->param('list');
+
+    my @add_rec = $cgi->param('add_rec') || $cgi->param('record');
+    my @del_item = $cgi->param('del_item');
+    my $shared = $cgi->param('shared');
+    my $name = $cgi->param('name');
+    my $success = 0;
+    my $list;
+
+    if($action eq 'create') {
+        $list = Fieldmapper::container::biblio_record_entry_bucket->new;
+        $list->name($name);
+        $list->owner($e->requestor->id);
+        $list->btype('bookbag');
+        $list->pub($shared ? 't' : 'f');
+        $success = $U->simplereq('open-ils.actor', 
+            'open-ils.actor.container.create', $e->authtoken, 'biblio', $list)
+
+    } else {
+
+        $list = $e->retrieve_container_biblio_record_entry_bucket($list_id);
+
+        return Apache2::Const::HTTP_BAD_REQUEST unless 
+            $list and $list->owner == $e->requestor->id;
+    }
+
+    if($action eq 'delete') {
+        $success = $U->simplereq('open-ils.actor', 
+            'open-ils.actor.container.full_delete', $e->authtoken, 'biblio', $list_id);
+
+    } elsif($action eq 'show') {
+        unless($U->is_true($list->pub)) {
+            $list->pub('t');
+            $success = $U->simplereq('open-ils.actor', 
+                'open-ils.actor.container.update', $e->authtoken, 'biblio', $list);
+        }
+
+    } elsif($action eq 'hide') {
+        if($U->is_true($list->pub)) {
+            $list->pub('f');
+            $success = $U->simplereq('open-ils.actor', 
+                'open-ils.actor.container.update', $e->authtoken, 'biblio', $list);
+        }
+
+    } elsif($action eq 'rename') {
+        if($name) {
+            $list->name($name);
+            $success = $U->simplereq('open-ils.actor', 
+                'open-ils.actor.container.update', $e->authtoken, 'biblio', $list);
+        }
+
+    } elsif($action eq 'add_rec') {
+        foreach my $add_rec (@add_rec) {
+            my $item = Fieldmapper::container::biblio_record_entry_bucket_item->new;
+            $item->bucket($list_id);
+            $item->target_biblio_record_entry($add_rec);
+            $success = $U->simplereq('open-ils.actor', 
+                'open-ils.actor.container.item.create', $e->authtoken, 'biblio', $item);
+            last unless $success;
+        }
+
+    } elsif($action eq 'del_item') {
+        foreach (@del_item) {
+            $success = $U->simplereq(
+                'open-ils.actor',
+                'open-ils.actor.container.item.delete', $e->authtoken, 'biblio', $_
+            );
+            last unless $success;
+        }
+    }
+
+    return $self->generic_redirect if $success;
+
+    $self->ctx->{bucket_action} = $action;
+    $self->ctx->{bucket_action_failed} = 1;
+    return Apache2::Const::OK;
+}
+
+1
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Container.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Container.pm
new file mode 100644 (file)
index 0000000..7f87104
--- /dev/null
@@ -0,0 +1,130 @@
+package OpenILS::WWW::EGCatLoader;
+use strict; use warnings;
+use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use OpenILS::Utils::Fieldmapper;
+use OpenILS::Application::AppUtils;
+my $U = 'OpenILS::Application::AppUtils';
+
+use constant COOKIE_ANON_CACHE => 'anoncache';
+use constant ANON_CACHE_MYLIST => 'mylist';
+
+# Retrieve the users cached records AKA 'My List'
+# Returns an empty list if there are no cached records
+sub fetch_mylist {
+    my ($self, $with_marc_xml) = @_;
+
+    my $list = [];
+    my $cache_key = $self->cgi->cookie(COOKIE_ANON_CACHE);
+
+    if($cache_key) {
+
+        $list = $U->simplereq(
+            'open-ils.actor',
+            'open-ils.actor.anon_cache.get_value', 
+            $cache_key, ANON_CACHE_MYLIST);
+
+        if(!$list) {
+            $cache_key = undef;
+            $list = [];
+        }
+    }
+
+    my $marc_xml;
+    if ($with_marc_xml) {
+        $marc_xml = $self->fetch_marc_xml_by_id($list);
+    }
+
+    return ($cache_key, $list, $marc_xml);
+}
+
+
+# Adds a record (by id) to My List, creating a new anon cache + list if necessary.
+sub load_mylist_add {
+    my $self = shift;
+    my $rec_id = $self->cgi->param('record');
+
+    my ($cache_key, $list) = $self->fetch_mylist;
+    push(@$list, $rec_id);
+
+    $cache_key = $U->simplereq(
+        'open-ils.actor',
+        'open-ils.actor.anon_cache.set_value', 
+        $cache_key, ANON_CACHE_MYLIST, $list);
+
+    return $self->mylist_action_redirect($cache_key);
+}
+
+# Removes a record ID from My List, or moves to an actual bookbag
+sub load_mylist_move {
+    my $self = shift;
+    my @rec_ids = $self->cgi->param('record');
+
+    my ($cache_key, $list) = $self->fetch_mylist;
+    return $self->mylist_action_redirect unless $cache_key;
+
+    my @keep;
+    foreach my $id (@$list) { push(@keep, $id) unless grep { $id eq $_ } @rec_ids; }
+
+    $cache_key = $U->simplereq(
+        'open-ils.actor',
+        'open-ils.actor.anon_cache.set_value', 
+        $cache_key, ANON_CACHE_MYLIST, \@keep
+    );
+
+    if ($self->ctx->{user} and $self->cgi->param('action') =~ /^\d+$/) {
+        # in this case, action becomes list_id
+        $self->load_myopac_bookbag_update('add_rec', $self->cgi->param('action'));
+        # XXX TODO: test for failure of above
+    }
+
+    return $self->mylist_action_redirect($cache_key);
+}
+
+sub load_cache_clear {
+    my $self = shift;
+    $self->clear_anon_cache;
+    return $self->mylist_action_redirect;
+}
+
+# Wipes the entire anonymous cache, including My List
+sub clear_anon_cache {
+    my $self = shift;
+    my $field = shift;
+
+    my $cache_key = $self->cgi->cookie(COOKIE_ANON_CACHE) or return;
+
+    $U->simplereq(
+        'open-ils.actor',
+        'open-ils.actor.anon_cache.delete_session', $cache_key)
+        if $cache_key;
+
+}
+
+# Called after an anon-cache / My List action occurs.  Redirect
+# to the redirect_url (cgi param) or referrer or home.
+sub mylist_action_redirect {
+    my $self = shift;
+    my $cache_key = shift;
+
+    return $self->generic_redirect(
+        undef, 
+        $self->cgi->cookie(
+            -name => COOKIE_ANON_CACHE,
+            -path => '/',
+            -value => ($cache_key) ? $cache_key : '',
+            -expires => ($cache_key) ? undef : '-1h'
+        )
+    );
+}
+
+sub load_mylist {
+    my ($self) = shift;
+    (undef, $self->ctx->{mylist}, $self->ctx->{mylist_marc_xml}) =
+        $self->fetch_mylist(1);
+
+    return Apache2::Const::OK;
+}
+
+1;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm
new file mode 100644 (file)
index 0000000..7b56ee4
--- /dev/null
@@ -0,0 +1,188 @@
+package OpenILS::WWW::EGCatLoader;
+use strict; use warnings;
+use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use OpenILS::Utils::Fieldmapper;
+use OpenILS::Application::AppUtils;
+my $U = 'OpenILS::Application::AppUtils';
+
+# context additions: 
+#   record : bre object
+sub load_record {
+    my $self = shift;
+    my $ctx = $self->ctx;
+    $ctx->{page} = 'record';
+
+    my $org = $self->cgi->param('loc') || $ctx->{aou_tree}->()->id;
+    my $depth = $self->cgi->param('depth') || 0;
+    my $copy_limit = int($self->cgi->param('copy_limit') || 10);
+    my $copy_offset = int($self->cgi->param('copy_offset') || 0);
+
+    my $rec_id = $ctx->{page_args}->[0]
+        or return Apache2::Const::HTTP_BAD_REQUEST;
+
+    # run copy retrieval in parallel to bib retrieval
+    # XXX unapi
+    my $copy_rec = OpenSRF::AppSession->create('open-ils.cstore')->request(
+        'open-ils.cstore.json_query.atomic', 
+        $self->mk_copy_query($rec_id, $org, $depth, $copy_limit, $copy_offset));
+
+    my (undef, @rec_data) = $self->get_records_and_facets([$rec_id], undef, {flesh => '{holdings_xml,mra}'});
+    $ctx->{bre_id} = $rec_data[0]->{id};
+    $ctx->{marc_xml} = $rec_data[0]->{marc_xml};
+
+    $ctx->{copies} = $copy_rec->gather(1);
+    $ctx->{copy_limit} = $copy_limit;
+    $ctx->{copy_offset} = $copy_offset;
+
+    $ctx->{have_holdings_to_show} = 0;
+
+    # XXX TODO we'll also need conditional logic to show MFHD-based holdings
+    if (
+        $ctx->{get_org_setting}->
+            ($org, "opac.fully_compressed_serial_holdings")
+    ) {
+        $ctx->{holding_summaries} =
+            $self->get_holding_summaries($rec_id, $org, $depth);
+
+        $ctx->{have_holdings_to_show} =
+            scalar(@{$ctx->{holding_summaries}->{basic}}) ||
+            scalar(@{$ctx->{holding_summaries}->{index}}) ||
+            scalar(@{$ctx->{holding_summaries}->{supplement}});
+    }
+
+    for my $expand ($self->cgi->param('expand')) {
+        $ctx->{"expand_$expand"} = 1;
+        if ($expand eq 'marchtml') {
+            $ctx->{marchtml} = $self->mk_marc_html($rec_id);
+        } elsif ($expand eq 'issues' and $ctx->{have_holdings_to_show}) {
+            $ctx->{expanded_holdings} =
+                $self->get_expanded_holdings($rec_id, $org, $depth);
+        }
+    }
+
+    return Apache2::Const::OK;
+}
+
+sub mk_copy_query {
+    my $self = shift;
+    my $rec_id = shift;
+    my $org = shift;
+    my $depth = shift;
+    my $copy_limit = shift;
+    my $copy_offset = shift;
+
+    my $query = {
+        select => {
+            acp => ['id', 'barcode', 'circ_lib', 'create_date', 'age_protect', 'holdable'],
+            acpl => [
+                {column => 'name', alias => 'copy_location'},
+                {column => 'holdable', alias => 'location_holdable'}
+            ],
+            ccs => [
+                {column => 'name', alias => 'copy_status'},
+                {column => 'holdable', alias => 'status_holdable'}
+            ],
+            acn => [
+                {column => 'label', alias => 'call_number_label'},
+                {column => 'id', alias => 'call_number'}
+            ],
+            circ => ['due_date'],
+        },
+        from => {
+            acp => {
+                acn => {},
+                acpl => {},
+                ccs => {},
+                circ => {type => 'left'},
+                aou => {}
+            }
+        },
+        where => {
+            '+acp' => {
+                deleted => 'f',
+                call_number => {
+                    in => {
+                        select => {acn => ['id']},
+                        from => 'acn',
+                        where => {record => $rec_id}
+                    }
+                },
+                circ_lib => {
+                    in => {
+                        select => {aou => [{
+                            column => 'id', 
+                            transform => 'actor.org_unit_descendants', 
+                            result_field => 'id', 
+                            params => [$depth]
+                        }]},
+                        from => 'aou',
+                        where => {id => $org}
+                    }
+                }
+            },
+            '+acn' => {deleted => 'f'},
+            '+circ' => {checkin_time => undef}
+        },
+
+        # Order is: copies with circ_lib=org, followed by circ_lib name, followed by call_number label
+        order_by => [
+            {class => 'aou', field => 'name'}, 
+            {class => 'acn', field => 'label'}
+        ],
+
+        limit => $copy_limit,
+        offset => $copy_offset
+    };
+
+    # Filter hidden items if this is the public catalog
+    unless($self->ctx->{is_staff}) { 
+        $query->{where}->{'+acp'}->{opac_visible} = 't';
+        $query->{where}->{'+acpl'}->{opac_visible} = 't';
+        $query->{where}->{'+ccs'}->{opac_visible} = 't';
+    }
+
+    return $query;
+    #return $self->editor->json_query($query);
+}
+
+sub mk_marc_html {
+    my($self, $rec_id) = @_;
+
+    # could be optimized considerably by performing the xslt on the already fetched record
+    return $U->simplereq(
+        'open-ils.search', 
+        'open-ils.search.biblio.record.html', $rec_id, 1);
+}
+
+sub get_holding_summaries {
+    my ($self, $rec_id, $org, $depth) = @_;
+
+    return (
+        create OpenSRF::AppSession("open-ils.serial")->request(
+            "open-ils.serial.bib.summary_statements",
+            $rec_id, {"org_id" => $org, "depth" => $depth}
+        )->gather(1)
+    );
+}
+
+sub get_expanded_holdings {
+    my ($self, $rec_id, $org, $depth) = @_;
+
+    my $holding_limit = int($self->cgi->param("holding_limit") || 10);
+    my $holding_offset = int($self->cgi->param("holding_offset") || 0);
+    my $type = $self->cgi->param("expand_holding_type");
+
+    return create OpenSRF::AppSession("open-ils.serial")->request(
+        "open-ils.serial.received_siss.retrieve.by_bib.atomic",
+        $rec_id, {
+            "ou" => $org, "depth" => $depth,
+            "limit" => $holding_limit, "offset" => $holding_offset,
+            "type" => $type
+        }
+    )->gather(1);
+}
+
+
+1;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
new file mode 100644 (file)
index 0000000..50a09f1
--- /dev/null
@@ -0,0 +1,181 @@
+package OpenILS::WWW::EGCatLoader;
+use strict; use warnings;
+use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use OpenILS::Utils::Fieldmapper;
+use OpenILS::Application::AppUtils;
+my $U = 'OpenILS::Application::AppUtils';
+
+
+sub _prepare_biblio_search_basics {
+    my ($cgi) = @_;
+
+    return $cgi->param('query') unless $cgi->param('qtype');
+
+    my %parts;
+    my @part_names = qw/qtype contains query/;
+    $parts{$_} = [ $cgi->param($_) ] for (@part_names);
+
+    my @chunks = ();
+    for (my $i = 0; $i < scalar @{$parts{'qtype'}}; $i++) {
+        my ($qtype, $contains, $query) = map { $parts{$_}->[$i] } @part_names;
+
+        next unless $query =~ /\S/;
+        push(@chunks, $qtype . ':') unless $qtype eq 'keyword' and $i == 0;
+
+        # This stuff probably will need refined or rethought to better handle
+        # the weird things Real Users will surely type in.
+        $contains = "" unless defined $contains; # silence warning
+        if ($contains eq 'nocontains') {
+            $query =~ s/"//g;
+            $query = ('"' . $query . '"') if index $query, ' ';
+            $query = '-' . $query;
+        } elsif ($contains eq 'phrase') {
+            $query =~ s/"//g;
+            $query = ('"' . $query . '"') if index $query, ' ';
+        } elsif ($contains eq 'exact') {
+            $query =~ s/[\^\$]//g;
+            $query = '^' . $query . '$';
+        }
+        push @chunks, $query;
+    }
+
+    return join(' ', @chunks);
+}
+
+sub _prepare_biblio_search {
+    my ($cgi, $ctx) = @_;
+
+    my $query = _prepare_biblio_search_basics($cgi);
+
+    $query = ('#' . $_ . ' ' . $query) foreach ($cgi->param('modifier'));
+
+    # filters
+    foreach (grep /^fi:/, $cgi->param) {
+        /:(-?\w+)$/ or next;
+        my $term = join(",", $cgi->param($_));
+        $query .= " $1($term)" if length $term;
+    }
+
+    if ($cgi->param('sort')) {
+        my ($axis, $desc) = split /\./, $cgi->param('sort');
+        $query .= " sort($axis)";
+        $query .= '#descending' if $desc;
+    }
+
+    if ($cgi->param('pubdate') && $cgi->param('date1')) {
+        if ($cgi->param('pubdate') eq 'between') {
+            $query .= ' between(' . $cgi->param('date1');
+            $query .= ',' .  $cgi->param('date2') if $cgi->param('date2');
+            $query .= ')';
+        } elsif ($cgi->param('pubdate') eq 'is') {
+            $query .= ' between(' . $cgi->param('date1') .
+                ',' .  $cgi->param('date1') . ')';  # sic, date1 twice
+        } else {
+            $query .= ' ' . $cgi->param('pubdate') .
+                '(' . $cgi->param('date1') . ')';
+        }
+    }
+
+    my $site;
+    my $org = $cgi->param('loc');
+    if (defined($org) and $org ne '' and ($org ne $ctx->{aou_tree}->()->id) and not $query =~ /site\(\S+\)/) {
+        $site = $ctx->{get_aou}->($org)->shortname;
+        $query .= " site($site)";
+    }
+
+    if(!$site) {
+        ($site) = ($query =~ /site\(([^\)]+)\)/);
+        $site ||= $ctx->{aou_tree}->()->shortname;
+    }
+
+
+    my $depth;
+    if (defined($cgi->param('depth')) and not $query =~ /depth\(\d+\)/) {
+        $depth = defined $cgi->param('depth') ?
+            $cgi->param('depth') : $ctx->{get_aou}->($site)->ou_type->depth;
+        $query .= " depth($depth)";
+    }
+
+    return ($query, $site, $depth);
+}
+
+# context additions: 
+#   page_size
+#   hit_count
+#   records : list of bre's and copy-count objects
+sub load_rresults {
+    my $self = shift;
+    my $cgi = $self->cgi;
+    my $ctx = $self->ctx;
+    my $e = $self->editor;
+
+    $ctx->{page} = 'rresult';
+    my $page = $cgi->param('page') || 0;
+    my $facet = $cgi->param('facet');
+    my $limit = $cgi->param('limit') || 10; # TODO user settings
+    my $loc = $cgi->param('loc');
+    my $offset = $page * $limit;
+
+    my ($query, $site, $depth) = _prepare_biblio_search($cgi, $ctx);
+
+    return $self->generic_redirect unless $query;
+
+    # Limit and offset will stay here. Everything else should be part of
+    # the query string, not special args.
+    my $args = {'limit' => $limit, 'offset' => $offset};
+
+    # Stuff these into the TT context so that templates can use them in redrawing forms
+    $ctx->{processed_search_query} = $query;
+
+    $query = "$query $facet" if $facet; # TODO
+
+    $logger->activity("EGWeb: [search] $query");
+
+    my $results;
+
+    try {
+
+        my $method = 'open-ils.search.biblio.multiclass.query';
+        $method .= '.staff' if $ctx->{is_staff};
+        $results = $U->simplereq('open-ils.search', $method, $args, $query, 1);
+
+    } catch Error with {
+        my $err = shift;
+        $logger->error("multiclass search error: $err");
+        $results = {count => 0, ids => []};
+    };
+
+    my $rec_ids = [map { $_->[0] } @{$results->{ids}}];
+
+    $ctx->{records} = [];
+    $ctx->{search_facets} = {};
+    $ctx->{page_size} = $limit;
+    $ctx->{hit_count} = $results->{count};
+
+    return Apache2::Const::OK if @$rec_ids == 0;
+
+    my ($facets, @data) = $self->get_records_and_facets(
+        $rec_ids, $results->{facet_key}, 
+        {
+            flesh => '{holdings_xml,mra}',
+            site => $site,
+            depth => $depth
+        }
+    );
+
+    # shove recs into context in search results order
+    for my $rec_id (@$rec_ids) {
+        push(
+            @{$ctx->{records}},
+            grep { $_->{id} == $rec_id } @data
+        );
+    }
+
+    $ctx->{search_facets} = $facets;
+
+    return Apache2::Const::OK;
+}
+
+1;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
new file mode 100644 (file)
index 0000000..8b12453
--- /dev/null
@@ -0,0 +1,247 @@
+package OpenILS::WWW::EGCatLoader;
+use strict; use warnings;
+use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use OpenILS::Utils::Fieldmapper;
+use OpenILS::Application::AppUtils;
+use OpenSRF::MultiSession;
+my $U = 'OpenILS::Application::AppUtils';
+
+my $ro_object_subs; # cached subs
+our %cache = ( # cached data
+    map => {aou => {}}, # others added dynamically as needed
+    list => {},
+    search => {},
+    org_settings => {}
+);
+
+sub init_ro_object_cache {
+    my $self = shift;
+    my $e = $self->editor;
+    my $ctx = $self->ctx;
+
+    if($ro_object_subs) {
+        # subs have been built.  insert into the context then move along.
+        $ctx->{$_} = $ro_object_subs->{$_} for keys %$ro_object_subs;
+        return;
+    }
+
+    # make all "field_safe" classes accesible by default in the template context
+    my @classes = grep {
+        ($Fieldmapper::fieldmap->{$_}->{field_safe} || '') =~ /true/i
+    } keys %{ $Fieldmapper::fieldmap };
+
+    for my $class (@classes) {
+
+        my $hint = $Fieldmapper::fieldmap->{$class}->{hint};
+        next if $hint eq 'aou'; # handled separately
+
+        my $ident_field =  $Fieldmapper::fieldmap->{$class}->{identity};
+        (my $eclass = $class) =~ s/Fieldmapper:://o;
+        $eclass =~ s/::/_/g;
+
+        my $list_key = "${hint}_list";
+        my $get_key = "get_$hint";
+        my $search_key = "search_$hint";
+
+        # Retrieve the full set of objects with class $hint
+        $ro_object_subs->{$list_key} = sub {
+            my $method = "retrieve_all_$eclass";
+            $cache{list}{$hint} = $e->$method() unless $cache{list}{$hint};
+            return $cache{list}{$hint};
+        };
+    
+        # locate object of class $hint with Ident field $id
+        $cache{map}{$hint} = {};
+        $ro_object_subs->{$get_key} = sub {
+            my $id = shift;
+            return $cache{map}{$hint}{$id} if $cache{map}{$hint}{$id}; 
+            ($cache{map}{$hint}{$id}) = grep { $_->$ident_field eq $id } @{$ro_object_subs->{$list_key}->()};
+            return $cache{map}{$hint}{$id};
+        };
+
+        # search for objects of class $hint where field=value
+        $cache{search}{$hint} = {};
+        $ro_object_subs->{$search_key} = sub {
+            my ($field, $val) = @_;
+            my $method = "search_$eclass";
+            $cache{search}{$hint}{$field} = {} unless $cache{search}{$hint}{$field};
+            $cache{search}{$hint}{$field}{$val} = $e->$method({$field => $val}) 
+                unless $cache{search}{$hint}{$field}{$val};
+            return $cache{search}{$hint}{$field}{$val};
+        };
+    }
+
+    $ro_object_subs->{aou_tree} = sub {
+
+        # fetch the org unit tree
+        unless($cache{aou_tree}) {
+            my $tree = $e->search_actor_org_unit([
+                           {   parent_ou => undef},
+                           {   flesh            => -1,
+                                   flesh_fields    => {aou =>  ['children']},
+                                   order_by        => {aou => 'name'}
+                           }
+                   ])->[0];
+
+            # flesh the org unit type for each org unit
+            # and simultaneously set the id => aou map cache
+            sub flesh_aout {
+                my $node = shift;
+                my $ro_object_subs = shift;
+                $node->ou_type( $ro_object_subs->{get_aout}->($node->ou_type) );
+                $cache{map}{aou}{$node->id} = $node;
+                flesh_aout($_, $ro_object_subs) foreach @{$node->children};
+            };
+            flesh_aout($tree, $ro_object_subs);
+
+            $cache{aou_tree} = $tree;
+        }
+
+        return $cache{aou_tree};
+    };
+
+    # Add a special handler for the tree-shaped org unit cache
+    $ro_object_subs->{get_aou} = sub {
+        my $org_id = shift;
+        $ro_object_subs->{aou_tree}->(); # force the org tree to load
+        return $cache{map}{aou}{$org_id};
+    };
+
+    # turns an ISO date into something TT can understand
+    $ro_object_subs->{parse_datetime} = sub {
+        my $date = shift;
+        $date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($date));
+        return sprintf(
+            "%0.2d:%0.2d:%0.2d %0.2d-%0.2d-%0.4d",
+            $date->hour,
+            $date->minute,
+            $date->second,
+            $date->day,
+            $date->month,
+            $date->year
+        );
+    };
+
+    # retrieve and cache org unit setting values
+    $ro_object_subs->{get_org_setting} = sub {
+        my($org_id, $setting) = @_;
+
+        $cache{org_settings}{$org_id} = {} 
+            unless $cache{org_settings}{$org_id};
+
+        $cache{org_settings}{$org_id}{$setting} = 
+            $U->ou_ancestor_setting_value($org_id, $setting)
+                unless exists $cache{org_settings}{$org_id}{$setting};
+
+        return $cache{org_settings}{$org_id}{$setting};
+    };
+
+    $ctx->{$_} = $ro_object_subs->{$_} for keys %$ro_object_subs;
+}
+
+sub generic_redirect {
+    my $self = shift;
+    my $url = shift;
+    my $cookie = shift; # can be an array of cgi.cookie's
+
+    $self->apache->print(
+        $self->cgi->redirect(
+            -url => $url || 
+                $self->cgi->param('redirect_to') || 
+                $self->ctx->{referer} || 
+                $self->ctx->{home_page},
+            -cookie => $cookie
+        )
+    );
+
+    return Apache2::Const::REDIRECT;
+}
+
+sub get_records_and_facets {
+    my ($self, $rec_ids, $facet_key, $unapi_args) = @_;
+
+    $unapi_args ||= {};
+    $unapi_args->{site} ||= $self->ctx->{aou_tree}->()->shortname;
+    $unapi_args->{depth} ||= $self->ctx->{aou_tree}->()->ou_type->depth;
+    $unapi_args->{flesh_depth} ||= 5;
+
+    my @data;
+    my $ses = OpenSRF::MultiSession->new(
+        app => 'open-ils.cstore',
+        cap => 10, # XXX config
+        success_handler => sub {
+            my($self, $req) = @_;
+            my $data = $req->{response}->[0]->content;
+            my $xml = XML::LibXML->new->parse_string($data->{'unapi.bre'})->documentElement;
+            my $bre_id =  $xml->find('*[@tag="901"]/*[@code="c"]')->[0]->textContent;
+            push(@data, {id => $bre_id, marc_xml => $xml});
+        }
+    );
+
+    $ses->request(
+        'open-ils.cstore.json_query',
+         {from => [
+            'unapi.bre', $_, 'marcxml','record', 
+            $unapi_args->{flesh}, 
+            $unapi_args->{site}, 
+            $unapi_args->{depth}, 
+            $unapi_args->{flesh_depth}, 
+        ]}
+    ) for @$rec_ids;
+
+    # collect the facet data
+    my $search = OpenSRF::AppSession->create('open-ils.search');
+    my $facet_req = $search->request(
+        'open-ils.search.facet_cache.retrieve', $facet_key, 10
+    ) if $facet_key;
+
+    # gather up the unapi recs
+    $ses->session_wait(1);
+
+    my $facets;
+    if ($facet_key) {
+        $facets = $facet_req->gather(1);
+        $facets->{$_} = {
+            cmf => $self->ctx->{get_cmf}->($_),
+            data => $facets->{$_}
+        } for keys %$facets;    # quick-n-dirty
+    } else {
+        $facets = undef;
+    }
+
+    return ($facets, @data);
+}
+
+# TODO: blend this code w/ ^-- get_records_and_facets
+sub fetch_marc_xml_by_id {
+    my ($self, $id_list) = @_;
+    $id_list = [$id_list] unless ref($id_list);
+
+    {
+        no warnings qw/numeric/;
+        $id_list = [map { int $_ } @$id_list];
+        $id_list = [grep { $_ > 0} @$id_list];
+    };
+
+    return {} if scalar(@$id_list) < 1;
+
+    # I'm just sure there needs to be some more efficient way to get all of
+    # this.
+    my $results = $self->editor->json_query({
+        "select" => {"bre" => ["id", "marc"]},
+        "from" => {"bre" => {}},
+        "where" => {"id" => $id_list}
+    }) or return $self->editor->die_event;
+
+    my $marc_xml = {};
+    for my $r (@$results) {
+        $marc_xml->{$r->{"id"}} =
+            (new XML::LibXML)->parse_string($r->{"marc"});
+    }
+
+    return $marc_xml;
+}
+
+1;
index ec765af..36e6797 100644 (file)
@@ -7,6 +7,7 @@ use File::stat;
 use Apache2::Const -compile => qw(OK DECLINED HTTP_INTERNAL_SERVER_ERROR);
 use Apache2::Log;
 use OpenSRF::EX qw(:try);
+use OpenILS::Utils::CStoreEditor;
 
 use constant OILS_HTTP_COOKIE_SKIN => 'oils:skin';
 use constant OILS_HTTP_COOKIE_THEME => 'oils:theme';
@@ -15,12 +16,13 @@ use constant OILS_HTTP_COOKIE_LOCALE => 'oils:locale';
 my $web_config;
 my $web_config_file;
 my $web_config_edit_time;
+my %lh_cache; # locale handlers
 
 sub import {
     my $self = shift;
     $web_config_file = shift || '';
     unless(-r $web_config_file) {
-        warn "Invalid web config $web_config_file";
+        warn "Invalid web config $web_config_file\n";
         return;
     }
     check_web_config();
@@ -32,26 +34,80 @@ sub handler {
     check_web_config($r); # option to disable this
     my $ctx = load_context($r);
     my $base = $ctx->{base_path};
+
+    $r->content_type('text/html; encoding=utf8');
+
     my($template, $page_args, $as_xml) = find_template($r, $base, $ctx);
+    $ctx->{page_args} = $page_args;
+
+    my $stat = run_context_loader($r, $ctx);
+
+    return $stat unless $stat == Apache2::Const::OK;
     return Apache2::Const::DECLINED unless $template;
 
     $template = $ctx->{skin} . "/$template";
-    $ctx->{page_args} = $page_args;
-    $r->content_type('text/html; encoding=utf8');
 
     my $tt = Template->new({
         OUTPUT => ($as_xml) ?  sub { parse_as_xml($r, $ctx, @_); } : $r,
         INCLUDE_PATH => $ctx->{template_paths},
+        DEBUG => $ctx->{debug_template},
+        PLUGINS => {
+            EGI18N => 'OpenILS::WWW::EGWeb::I18NFilter',
+            CGI_utf8 => 'OpenILS::WWW::EGWeb::CGI_utf8'
+        }
     });
 
-    unless($tt->process($template, {ctx => $ctx})) {
-        $r->log->warn('Template error: ' . $tt->error);
+    unless($tt->process($template, {ctx => $ctx, l => set_text_handler($ctx, $r)})) {
+        $r->log->warn('egweb: template error: ' . $tt->error);
         return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR;
     }
 
     return Apache2::Const::OK;
 }
 
+sub set_text_handler {
+    my $ctx = shift;
+    my $r = shift;
+
+    my $locale = $ctx->{locale};
+    $locale =~ s/-/_/g;
+
+    $r->log->debug("egweb: messages locale = $locale");
+
+    unless($lh_cache{$locale}) {
+        $r->log->info("egweb: Unsupported locale: $locale");
+        $lh_cache{$locale} = $lh_cache{'en_US'};
+    }
+
+    return $OpenILS::WWW::EGWeb::I18NFilter::maketext = 
+        sub { return $lh_cache{$locale}->maketext(@_); };
+}
+
+
+
+sub run_context_loader {
+    my $r = shift;
+    my $ctx = shift;
+
+    my $stat = Apache2::Const::OK;
+
+    my $loader = $r->dir_config('OILSWebContextLoader');
+    return $stat unless $loader;
+
+    eval {
+        $loader->use;
+        $stat = $loader->new($r, $ctx)->load;
+    };
+
+    if($@) {
+        $r->log->error("egweb: Context Loader error: $@");
+        return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    $r->log->debug("egweb: context loader resulted in status $stat");
+    return $stat;
+}
+
 sub parse_as_xml {
     my $r = shift;
     my $ctx = shift;
@@ -65,9 +121,9 @@ sub parse_as_xml {
         $data = $ctx->{final_dtd} . "\n" . $data;
         $success = 1;
     } otherwise {
-       my $e = shift;
+           my $e = shift;
         my $err = "Invalid XML: $e";
-        $r->log->error($err);
+        $r->log->error("egweb: $err");
         $r->content_type('text/plain; encoding=utf8');
         $r->print("\n$err\n\n$data");
     };
@@ -79,16 +135,23 @@ sub parse_as_xml {
 sub load_context {
     my $r = shift;
     my $cgi = CGI->new;
-    my $ctx = $web_config->{ctx};
+    my $ctx = {}; # new context for each page load
+    $ctx->{$_} = $web_config->{base_ctx}->{$_} for keys %{$web_config->{base_ctx}};
     $ctx->{hostname} = $r->hostname;
     $ctx->{base_url} = $cgi->url(-base => 1);
     $ctx->{skin} = $cgi->cookie(OILS_HTTP_COOKIE_SKIN) || 'default';
     $ctx->{theme} = $cgi->cookie(OILS_HTTP_COOKIE_THEME) || 'default';
+
     $ctx->{locale} = 
         $cgi->cookie(OILS_HTTP_COOKIE_LOCALE) || 
         parse_accept_lang($r->headers_in->get('Accept-Language')) || 'en-US';
-    $r->log->debug('skin = ' . $ctx->{skin} . ' : theme = ' . 
-        $ctx->{theme} . ' : locale = ' . $ctx->{locale});
+
+    my $mprefix = $ctx->{media_prefix};
+    if($mprefix and $mprefix !~ /^http/ and $mprefix !~ /^\//) {
+        # if a hostname is provided /w no protocol, match the protocol to the current page
+        $ctx->{media_prefix} = ($cgi->https) ? "https://$mprefix" : "http://$mprefix";
+    }
+
     return $ctx;
 }
 
@@ -146,7 +209,7 @@ sub find_template {
             last unless $localpath;
             for my $tpath (@{$ctx->{template_paths}}) {
                 my $fpath = "$tpath/$skin/$localpath.$ext";
-                $r->log->debug("looking at possible template $fpath");
+                $r->log->debug("egweb: looking at possible template $fpath");
                 if(-r $fpath) {
                     $template = "$localpath.$ext";
                     last;
@@ -161,12 +224,12 @@ sub find_template {
 
         # no template configured or found
         unless($template) {
-            $r->log->warn("No template configured for path $path");
+            $r->log->debug("egweb: No template configured for path $path");
             return ();
         }
     }
 
-    $r->log->debug("template = $template : page args = @$page_args");
+    $r->log->debug("egweb: template = $template : page args = @$page_args");
     return ($template, $page_args, $as_xml);
 }
 
@@ -176,12 +239,46 @@ sub check_web_config {
     my $r = shift;
     my $epoch = stat($web_config_file)->mtime;
     unless($web_config_edit_time and $web_config_edit_time == $epoch) {
-        $r->log->debug("Reloading web config after edit...") if $r;
+        $r->log->debug("egweb: Reloading web config after edit...") if $r;
         $web_config_edit_time = $epoch;
         $web_config = parse_config($web_config_file);
     }
 }
 
+# Create an I18N sub-module for each supported locale
+# Each module creates its own MakeText lexicon by parsing .po/.mo files
+sub load_locale_handlers {
+    my $ctx = shift;
+    my $locales = $ctx->{locales};
+
+    $locales->{en_US} = {} unless exists $locales->{en_US};
+
+    for my $lang (keys %$locales) {
+        my $messages = $locales->{$lang};
+        $messages = '' if ref $messages; # empty {}
+
+        # TODO Can we do this without eval?
+        my $eval = <<EVAL;
+            package OpenILS::WWW::EGWeb::I18N::$lang;
+            use base 'OpenILS::WWW::EGWeb::I18N';
+            if(\$messages) {
+                use Locale::Maketext::Lexicon::Gettext;
+                if(open F, '$messages') {
+                    our %Lexicon = (%Lexicon, %{ Locale::Maketext::Lexicon::Gettext->parse(<F>) });
+                    close F;
+                } else {
+                    warn "EGWeb: unable to open messages file: $messages"; 
+                }
+            }
+EVAL
+        eval $eval;
+        warn "$@\n" if $@; # TODO better logging
+        $lh_cache{$lang} = "OpenILS::WWW::EGWeb::I18N::$lang"->new;
+    }
+}
+
+
+
 sub parse_config {
     my $cfg_file = shift;
     my $data = XML::Simple->new->XMLin($cfg_file);
@@ -191,9 +288,12 @@ sub parse_config {
     $ctx->{media_prefix} = (ref $data->{media_prefix}) ? '' : $data->{media_prefix};
     $ctx->{base_path} = (ref $data->{base_path}) ? '' : $data->{base_path};
     $ctx->{template_paths} = [];
-    $ctx->{force_valid_xml} = ($data->{force_valid_xml} =~ /true/io) ? 1 : 0;
+    $ctx->{force_valid_xml} = ( ($data->{force_valid_xml}||'') =~ /true/io) ? 1 : 0;
+    $ctx->{debug_template} = ( ($data->{debug_template}||'')  =~ /true/io) ? 1 : 0;
     $ctx->{default_template_extension} = $data->{default_template_extension} || 'tt2';
     $ctx->{web_dir} = $data->{web_dir};
+    $ctx->{locales} = $data->{locales};
+    load_locale_handlers($ctx);
 
     my $tpaths = $data->{template_paths}->{path};
     $tpaths = [$tpaths] unless ref $tpaths;
@@ -217,7 +317,7 @@ sub parse_config {
         }
     }
 
-    return {ctx => $ctx, handlers => $handlers};
+    return {base_ctx => $ctx, handlers => $handlers};
 }
 
 package PathConfig;
@@ -226,5 +326,9 @@ sub new {
     return bless(\%args, $class);
 }
 
+# base class for all supported locales
+package OpenILS::WWW::EGWeb::I18N;
+use base 'Locale::Maketext';
+our %Lexicon = (_AUTO => 1);
 
 1;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGWeb/CGI_utf8.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGWeb/CGI_utf8.pm
new file mode 100644 (file)
index 0000000..0239e1b
--- /dev/null
@@ -0,0 +1,44 @@
+package OpenILS::WWW::EGWeb::CGI_utf8;
+
+# The code in this module is copied from (except for a tiny modification)
+# Template::Plugin::CGI, which is written by:
+#
+# Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/>
+#
+# Copyright (C) 1996-2007 Andy Wardley.  All Rights Reserved.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+use strict;
+use warnings;
+use base 'Template::Plugin';
+use CGI qw(:all -utf8);
+
+sub new {
+    my $class   = shift;
+    my $context = shift;
+    new CGI(@_);
+}
+
+# monkeypatch CGI::params() method to Do The Right Thing in TT land
+
+sub CGI::params {
+    my $self = shift;
+    local $" = ', ';
+
+    return $self->{ _TT_PARAMS } ||= do {
+        # must call Vars() in a list context to receive
+        # plain list of key/vals rather than a tied hash
+        my $params = { $self->Vars() };
+
+        # convert any null separated values into lists
+        @$params{ keys %$params } = map { 
+            /\0/ ? [ split /\0/ ] : $_ 
+        } values %$params;
+
+        $params;
+    };
+}
+
+1;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGWeb/I18NFilter.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGWeb/I18NFilter.pm
new file mode 100644 (file)
index 0000000..cc931fa
--- /dev/null
@@ -0,0 +1,19 @@
+package OpenILS::WWW::EGWeb::I18NFilter;
+use Template::Plugin::Filter;
+use base qw(Template::Plugin::Filter);
+our $DYNAMIC = 1;
+our $maketext;
+
+sub filter {
+    my ($self, $text, $args) = @_;
+    return $maketext->($text, @$args);
+}
+
+sub init {
+    my $self = shift;
+    $self->install_filter('l');
+    return $self;
+}
+
+1;
+
diff --git a/Open-ILS/src/support-scripts/test-scripts/unapi_bench.pl b/Open-ILS/src/support-scripts/test-scripts/unapi_bench.pl
new file mode 100755 (executable)
index 0000000..5b38b28
--- /dev/null
@@ -0,0 +1,336 @@
+#!/usr/bin/perl
+require '../oils_header.pl';
+use strict; use warnings;
+use Time::HiRes qw/time usleep/;
+use Data::Dumper;
+use OpenSRF::Utils::JSON;
+use OpenILS::Utils::CStoreEditor;
+use XML::LibXML;
+
+#-----------------------------------------------------------------------------
+# Does a checkout, renew, and checkin 
+#-----------------------------------------------------------------------------
+
+my @recs = (1,2,3,4,5,6,7,8,9,10);
+
+osrf_connect(shift() || '/openils/conf/opensrf_core.xml');
+
+my $e = OpenILS::Utils::CStoreEditor->new;
+
+sub xptext {
+    my($node, $path) = @_;
+    #my $res = $node->findnodes($path);
+    my $res = $node->find($path);
+    return '' unless $res and $res->[0];
+    return $res->[0]->textContent;
+}
+
+sub get_bib_attrs {
+    my $xml = shift;
+    return {
+        isbn => xptext($xml, '*[@tag="020"]/*[@code="a"]'),
+        upc => xptext($xml,'*[@tag="024"]/*[@code="a"]'),
+        issn => xptext($xml,'*[@tag="022"]/*[@code="a"]'),
+        title => xptext($xml,'*[@tag="245"]/*[@code="a"]'),
+        author => xptext($xml,'*[@tag="100"]/*[@code="a"]'),
+        publisher => xptext($xml,'*[@tag="260"]/*[@code="b"]'),
+        pubdate => xptext($xml,'*[@tag="260"]/*[@code="c"]'),
+        edition => xptext($xml,'*[@tag="250"]/*[@code="a"]'),
+    };
+}
+
+sub unapi {
+    my @recs = @_;
+    my $start = time();
+
+    my $ses1 = OpenSRF::AppSession->create('open-ils.cstore');
+    my $ses2 = OpenSRF::AppSession->create('open-ils.cstore');
+    my $ses3 = OpenSRF::AppSession->create('open-ils.cstore');
+    my ($req1, $req2, $req3);
+
+    my %records;
+    while(@recs) {
+        my ($id1, $id2, $id3) = (pop @recs, pop @recs, pop @recs);
+
+        for my $r ($req1, $req2, $req3) {
+            if($r) {
+                my $data = $r->gather(1);
+                my $xml = XML::LibXML->new->parse_string($data->{'unapi.bre'});
+                $xml = $xml->documentElement;
+                my $attrs = get_bib_attrs($xml);
+                my $rec_id =  xptext($xml,'*[@tag="901"]/*[@code="c"]');
+                $records{$rec_id}{$_} = $attrs->{$_} for keys %$attrs;
+
+                my $rvols = [];
+                for my $volnode ($xml->findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]')) {
+                    my $vol = {}; 
+                    $vol->{copies} = [];
+                    $vol->{label} = $volnode->getAttribute('label');
+                    for my $copynode ($volnode->getElementsByLocalName('copy')) {
+                        my $copy = {};   
+                        $copy->{barcode} = $copynode->getAttribute('barcode');
+                        push(@{$vol->{copies}}, $copy);
+                    }
+                    push(@{$records{$rec_id}->{volumes}}, $vol);
+                }
+
+            }
+        }
+
+        $req1 = ($id1) ? $ses1->request('open-ils.cstore.json_query', {from => ['unapi.bre', $id1, 'marcxml', 'record', '{holdings_xml,acp}', 'CONS']}) : undef;
+        $req2 = ($id2) ? $ses1->request('open-ils.cstore.json_query', {from => ['unapi.bre', $id2, 'marcxml', 'record', '{holdings_xml,acp}', 'CONS']}) : undef;
+        $req3 = ($id3) ? $ses1->request('open-ils.cstore.json_query', {from => ['unapi.bre', $id3, 'marcxml', 'record', '{holdings_xml,acp}', 'CONS']}) : undef;
+    }
+
+
+    for my $r ($req1, $req2, $req3) {
+        if($r) {
+            my $data = $r->gather(1);
+            my $xml = XML::LibXML->new->parse_string($data->{'unapi.bre'});
+            $xml = $xml->documentElement;
+            my $attrs = get_bib_attrs($xml);
+            my $rec_id =  xptext($xml,'*[@tag="901"]/*[@code="c"]');
+            $records{$rec_id}{$_} = $attrs->{$_} for keys %$attrs;
+
+            my $rvols = [];
+            for my $volnode ($xml->findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]')) {
+                my $vol = {}; 
+                $vol->{copies} = [];
+                $vol->{label} = $volnode->getAttribute('label');
+                for my $copynode ($volnode->getElementsByLocalName('copy')) {
+                    my $copy = {};   
+                    $copy->{barcode} = $copynode->getAttribute('barcode');
+                    push(@{$vol->{copies}}, $copy);
+                }
+                push(@{$records{$rec_id}->{volumes}}, $vol);
+            }
+
+        }
+    }
+
+    my $duration = time() - $start;
+
+    for my $rec_id (keys %records) {
+        my $rec = $records{$rec_id};
+        print sprintf("%d [%s] has %d volumes and %d copies\n",
+            $rec_id, $rec->{title}, 
+            scalar(@{$rec->{volumes}}),
+            scalar(map { @{$_->{copies}} } @{$rec->{volumes}}));
+    }
+
+    #note, unapi.biblio_record_entry_feed per record performs the same as unapi.bre pre record
+    print "\nunapi 'unapi.bre' duration is $duration\n\n";
+}
+
+sub unapi_spread {
+    my @recs = @_;
+    my %records;
+    my $start = time();
+
+    my @reqs;
+    for my $rec_id (@recs) {
+
+        my $ses = OpenSRF::AppSession->create('open-ils.cstore');
+        my $req = $ses->request(
+            'open-ils.cstore.json_query', 
+            {from => ['unapi.bre', $rec_id, 'marcxml', 'record', '{holdings_xml,acp}', 'CONS']});
+
+        push(@reqs, $req);
+    }
+
+    for my $req (@reqs) {
+
+        my $data = $req->gather(1);
+        my $xml = XML::LibXML->new->parse_string($data->{'unapi.bre'});
+        $xml = $xml->documentElement;
+        my $attrs = get_bib_attrs($xml);
+        my $rec_id =  xptext($xml,'*[@tag="901"]/*[@code="c"]');
+        $records{$rec_id}{$_} = $attrs->{$_} for keys %$attrs;
+
+        my $rvols = [];
+        for my $volnode ($xml->findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]')) {
+            my $vol = {}; 
+            $vol->{copies} = [];
+            $vol->{label} = $volnode->getAttribute('label');
+            for my $copynode ($volnode->getElementsByLocalName('copy')) {
+                my $copy = {};   
+                $copy->{barcode} = $copynode->getAttribute('barcode');
+                push(@{$vol->{copies}}, $copy);
+            }
+            push(@{$records{$rec_id}->{volumes}}, $vol);
+        }
+    }
+
+    my $duration = time() - $start;
+
+    for my $rec_id (keys %records) {
+        my $rec = $records{$rec_id};
+        print sprintf("%d [%s] has %d volumes and %d copies\n",
+            $rec_id, $rec->{title}, 
+            scalar(@{$rec->{volumes}}),
+            scalar(map { @{$_->{copies}} } @{$rec->{volumes}}));
+    }
+
+    #note, unapi.biblio_record_entry_feed per record performs the same as unapi.bre pre record
+    print "\nunapi 'unapi.bre' spread duration is $duration\n\n";
+}
+
+
+
+sub unapi_batch {
+    my @recs = @_;
+    my $start = time();
+
+    my $data = $e->json_query({from => ['unapi.biblio_record_entry_feed', "{".join(',',@recs)."}", 'marcxml', '{holdings_xml,acp}', 'CONS']})->[0];
+    my $xml = XML::LibXML->new->parse_string($data->{'unapi.biblio_record_entry_feed'});
+
+    my %records;
+    for my $rec_xml ($xml->documentElement->getElementsByLocalName('record')) { 
+
+        my $attrs = get_bib_attrs($rec_xml);
+        my $rec_id =  xptext($rec_xml,'*[@tag="901"]/*[@code="c"]');
+        #print "REC = $rec_xml : $rec_id : " . $attrs->{title} . "\n" . $rec_xml->toString . "\n";
+        $records{$rec_id}{$_} = $attrs->{$_} for keys %$attrs;
+
+        my $rvols = [];
+        for my $volnode ($rec_xml->findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]')) {
+            my $vol = {}; 
+            $vol->{copies} = [];
+            $vol->{label} = $volnode->getAttribute('label');
+            for my $copynode ($volnode->getElementsByLocalName('copy')) {
+                my $copy = {};   
+                $copy->{barcode} = $copynode->getAttribute('barcode');
+                push(@{$vol->{copies}}, $copy);
+            }
+            push(@{$records{$rec_id}->{volumes}}, $vol);
+        }
+    }
+
+    my $duration = time() - $start;
+
+    for my $rec_id (keys %records) {
+        my $rec = $records{$rec_id};
+        print sprintf("%d [%s] has %d volumes and %d copies\n",
+            $rec_id, $rec->{title}, 
+            scalar(@{$rec->{volumes}}),
+            scalar(map { @{$_->{copies}} } @{$rec->{volumes}}));
+    }
+    print "\nunapi 'batch feed' duration is $duration\n\n";
+}
+
+sub direct_spread {
+    my @recs = @_;
+    my %records;
+    my $start = time();
+
+    my $query = {
+        flesh => 4, 
+        flesh_fields => {
+            bre => ['call_numbers'], 
+            acn => ['copies', 'uris'], 
+            acp => ['location', 'stat_cat_entries', 'parts'],
+            ascecm => ['stat_cat', 'stat_cat_entry'],
+            acpm => ['part']
+        }
+    };
+
+    my @reqs;
+    for my $rec_id (@recs) {
+        my $ses = OpenSRF::AppSession->create('open-ils.cstore');
+        my $req = $ses->request(
+            'open-ils.cstore.direct.biblio.record_entry.search', {id => $rec_id}, $query);
+        push(@reqs, $req);
+    }
+
+    $records{$_}{counts} = $e->json_query({from => ['asset.record_copy_count', 1, $_, 0]})->[0] for @recs;
+    for my $req (@reqs) {
+        my $bre = $req->gather(1);
+        my $xml = XML::LibXML->new->parse_string($bre->marc)->documentElement;
+        my $attrs = get_bib_attrs($xml);
+        $records{$bre->id}{record} = $bre;
+        $records{$bre->id}{$_} = $attrs->{$_} for keys %$attrs;
+    }
+
+    my $duration = time() - $start;
+
+    for my $rec_id (keys %records) {
+        my $rec = $records{$rec_id};
+        print sprintf("%d [%s] has %d volumes and %d copies\n",
+            $rec_id, $rec->{title}, 
+            scalar(@{$rec->{record}->call_numbers}), 
+            scalar(map { @{$_->copies} } @{$rec->{record}->call_numbers}));
+    }
+
+    print "\n'direct' spread calls processing duration is $duration\n\n";
+}
+
+
+sub direct {
+    my @recs = @_;
+    my %records;
+
+    my $start = time();
+
+    my $ses1 = OpenSRF::AppSession->create('open-ils.cstore');
+    my $ses2 = OpenSRF::AppSession->create('open-ils.cstore');
+    my $ses3 = OpenSRF::AppSession->create('open-ils.cstore');
+    my ($req1, $req2, $req3);
+
+    my $query = {
+        flesh => 5, 
+        flesh_fields => {
+            bre => ['call_numbers'], 
+            acn => ['copies', 'uris'], 
+            acp => ['location', 'stat_cat_entries', 'parts'],
+            ascecm => ['stat_cat', 'stat_cat_entry'],
+            acpm => ['part']
+        }
+    };
+
+    my $first = 1;
+    while(@recs) {
+        my ($id1, $id2, $id3) = (pop @recs, pop @recs, pop @recs);
+
+        for my $r ($req1, $req2, $req3) {
+            last unless $r;
+            my $bre = $r->gather(1);
+            my $xml = XML::LibXML->new->parse_string($bre->marc)->documentElement;
+            my $attrs = get_bib_attrs($xml);
+            $records{$bre->id}{record} = $bre;
+            $records{$bre->id}{$_} = $attrs->{$_} for keys %$attrs;
+        }
+
+        $req1 = ($id1) ? $ses1->request('open-ils.cstore.direct.biblio.record_entry.search', {id => $id1}, $query) : undef;
+        $req2 = ($id2) ? $ses1->request('open-ils.cstore.direct.biblio.record_entry.search', {id => $id2}, $query) : undef;
+        $req3 = ($id3) ? $ses1->request('open-ils.cstore.direct.biblio.record_entry.search', {id => $id3}, $query) : undef;
+        
+        if($first) {
+            $records{$_}{counts} = $e->json_query({from => ['asset.record_copy_count', 1, $_, 0]})->[0] for @recs;
+            $first = 0;
+        }
+    }
+
+    for my $r ($req1, $req2, $req3) {
+        last unless $r;
+        my $bre = $r->gather(1);
+        my $xml = XML::LibXML->new->parse_string($bre->marc)->documentElement;
+        my $attrs = get_bib_attrs($xml);
+        $records{$bre->id}{record} = $bre;
+        $records{$bre->id}{$_} = $attrs->{$_} for keys %$attrs;
+    }
+
+
+    my $duration = time() - $start;
+
+    for my $rec_id (keys %records) {
+        my $rec = $records{$rec_id};
+        print sprintf("%d [%s] has %d volumes and %d copies\n",
+            $rec_id, $rec->{title}, 
+            scalar(@{$rec->{record}->call_numbers}), 
+            scalar(map { @{$_->copies} } @{$rec->{record}->call_numbers}));
+    }
+
+    print "\n'direct' calls processing duration is $duration\n\n";
+}
+
+for (0..1) { direct(@recs); unapi(@recs); unapi_batch(@recs); unapi_spread(@recs); direct_spread(@recs); }
diff --git a/Open-ILS/web/css/skin/default/opac/contentslider.css b/Open-ILS/web/css/skin/default/opac/contentslider.css
new file mode 100644 (file)
index 0000000..64a6d25
--- /dev/null
@@ -0,0 +1,39 @@
+.sliderwrapper{
+position: relative; /*leave as is*/
+overflow: hidden; /*leave as is*/
+width: 675px; /*width of featured content slider*/
+height: 213px;
+}
+
+
+
+.sliderwrapper .contentdiv{
+visibility: hidden; /*leave as is*/
+position: absolute; /*leave as is*/ 
+left: 0;  /*leave as is*/
+top: 0;  /*leave as is*/
+width: 675px; /*width of content DIVs within slider. Total width should equal slider's inner width (390+5+5=400) */
+height: 100%;
+filter:progid:DXImageTransform.Microsoft.alpha(opacity=100);
+-moz-opacity: 1;
+opacity: 1;
+}
+
+.pagination{
+width: 400px; /*Width of pagination DIV. Total width should equal slider's outer width (400+10+10=420)*/
+text-align: right;
+background-color: navy;
+padding: 5px 10px;
+}
+
+.pagination a{
+padding: 0 5px;
+text-decoration: none; 
+color: #00007D;
+background: white;
+}
+
+.pagination a:hover, .pagination a.selected{
+color: #000;
+background-color: #FEE496;
+}
\ No newline at end of file
diff --git a/Open-ILS/web/css/skin/default/opac/semiauto.css b/Open-ILS/web/css/skin/default/opac/semiauto.css
new file mode 100644 (file)
index 0000000..e4e9eb7
--- /dev/null
@@ -0,0 +1,183 @@
+/* once done renaming and everything, combine with style.css */
+
+/* Verfied in-use classes --------------------------- */
+.opac-auto-004 { background: #E0F0E0; }
+.opac-auto-009 { border: 3px solid #E0E0E0; }
+.opac-auto-010 { border-bottom: 1px dotted #ccc; padding-top: 10px; }
+.opac-auto-011 { border-bottom: 1px dotted #ccc; padding-top: 6px; }
+.opac-auto-012 { border-bottom: none; }
+.opac-auto-013 { border-bottom: none; *height: 0px; }
+.opac-auto-015 { border-left: 1px solid #e9ebf3; padding-right: 27px; }
+.opac-auto-017 { border: none; width: 100%; }
+.opac-auto-018 { border-top: 1px dotted #ccc; padding-top: 17px; }
+.clear-both { clear: both; }
+.common-no-pad { clear: both; height: 0px; margin: 0px; padding: 0px; }
+.common-full-pad { clear: both; height: 15px; }
+.opac-auto-029 { color: #333; font-weight: bold; font-size: 13px; }
+.opac-auto-030 { color: #545454; }
+.opac-auto-031 { color: #9999FF; padding-left: 10px; font-size: 7pt; font-weight: 300; }
+.red { color: red; }
+.bold-red { color: red; font-weight: bold }
+.pointer { cursor: pointer; }
+/* ------------------------------------------- */
+
+
+#lib_selector_span { display: none }
+.float-left { float: left; }
+.bookbag-share { float: left; padding: 5px 0; }
+.bookbag-controls { float: left; padding: 5px 0px 0px 10px; }
+.left-corner { float: left; width: 163px; height: 30px; background: url('/images/utils-corner-mid.png') repeat-x top; }
+.float-right { float: right; }
+.opac-auto-045 { float: right; margin-right: 17px; }
+.opac-auto-046 { float: right; width: 214px; }
+.opac-auto-047 { float: right; width: 353px; background: #ccc; padding: 10px; margin-top: 7px; }
+.opac-auto-048 { float: right; width: 65px; }
+#they_said_dont_touch { float: right; width: 675px; height: 213px; color: green; overflow: hidden; }
+.opac-auto-050 { float: right; width: 85px; }
+.ten-px { font-size: 10px; }
+.eleven-px { font-size: 11px; }
+.eight-pt { font-size: 8pt; }
+.opac-auto-054 { font-size: 8pt; padding-left: 20px; }
+.bold { font-weight: bold; }
+.opac-auto-057 { font-weight: bold; padding: 5px; margin: 5px; width: 100%; }
+.opac-auto-058 { font-weight: bold; padding-left: 10px; }
+#anon_list_name { font-weight: bold; padding-right: 10px; }
+.opac-auto-060 { font-weight: normal; }
+.opac-auto-061 { height: 0px; border-top: 1px solid #b7b7b7; border-bottom: 1px solid #d4d4d4; margin: 15px 0px; }
+.small-height { height: 10px; }
+.normal-height { height: 15px; }
+.big-height { height: 20px; }
+.very-big-height { height: 30px; }
+#gold-links-holder { height: 24px; background: #252525; }
+.opac-auto-067 { margin: 3px; width: 100%; }
+.big-block { margin: auto; width: 974px; height: 0px; }
+.opac-auto-069 { margin-bottom: 10px; }
+.opac-auto-070 { margin-bottom: 20px; }
+.opac-auto-071 { margin-bottom: 5px; }
+.opac-auto-072 { margin-left: 20px; }
+.bookbag-list { margin-left: 5px; margin-top: 5px; width: 91%; border: 0;}
+#cn_browse_where { margin-left: 6px; }
+.opac-auto-075 { margin-right: 20px; }
+.opac-auto-076 { margin-right: 3px; }
+.opac-auto-077 { margin-right: 4px; position: relative; top: -10px; }
+.opac-auto-078 { margin-right: 7px; }
+.opac-auto-079 { margin-top: 10px; }
+.opac-auto-080 { margin-top: 10px; margin-bottom: 10px; }
+.opac-auto-081 { margin-top: 13px; }
+.opac-auto-082 { margin-top: 29px; }
+.opac-auto-083 { margin-top: 2px; }
+.opac-auto-084 { margin-top: 5px; }
+.opac-auto-085 { margin-top: 6px; margin-left: 20px; width: 250px; padding: 5px; }
+.opac-auto-086 { margin-top: 8px; }
+.opac-auto-087 { max-width: 11em; }
+.opac-auto-088 { padding: 0px; }
+.opac-auto-089 { padding: 0px 10px; }
+.opac-auto-090 { padding: 10px; }
+.opac-auto-091 { padding: 10px 0px; }
+.opac-auto-092 { padding: 4px; text-align: center; }
+.pad-bottom-five { padding: 5px; }
+.opac-auto-094 { padding: 5px 7px 0px 0px; }
+.opac-auto-095 { padding: 5px 7px 0px 0px; white-space: nowrap; }
+.opac-auto-096 { padding: 6px }
+.opac-auto-097 { padding: 8px 0px 6px 0px; width: 100%; border: 0; }
+.opac-auto-097b { padding: 8px 0px 6px 0px; border: 0; }
+.opac-auto-098 { padding-bottom: 10px; }
+.opac-auto-099 { padding-bottom: 12px; color: #666; }
+.opac-auto-100 { padding-bottom: 16px; }
+.opac-auto-101 { padding-bottom: 1px; }
+.opac-auto-102 { padding-bottom: 7px; }
+.opac-auto-103 { padding-left: 10px; }
+.opac-auto-104 { padding-left: 11px; padding-right: 11px; }
+.opac-auto-105 { padding-left: 11px; padding-right: 13px; }
+.opac-auto-106 { padding-left: 15px; }
+.opac-auto-107 { padding-left: 15px; padding-bottom: 10px; }
+.opac-auto-108 { padding-left: 5px; }
+.opac-auto-109 { padding-left: 5px; padding-bottom: 10px; }
+.opac-auto-110 { padding-left: 6px; }
+.opac-auto-111 { padding-left: 8px; }
+.opac-auto-112 { padding-left: 9px; }
+.opac-auto-113 { padding-right: 10px; }
+.opac-auto-114 { padding-right: 15px; padding-left: 15px; }
+.opac-auto-115 { padding-right: 20px; }
+.opac-auto-116 { padding-right: 5px; }
+.opac-auto-117 { padding-right: 7px; }
+.pad-top-ten { padding-top: 10px; }
+.opac-auto-119 { padding-top: 14px; }
+.opac-auto-120 { padding-top: 5px; }
+.opac-auto-121 { padding-top: 6px; }
+.opac-auto-122 { padding-top: 7px; }
+.opac-auto-123 { padding-top: 8px; }
+.pos-abs { position: absolute; }
+#new_cat_link_holder { position: absolute; z-index: 101; }
+#new_cat_link_holder a { display: block; width: 675px; height: 213px; }
+.pos-rel { position: relative; }
+#search-box table { position: relative; left: -10px; }
+.opac-auto-129 { position: relative; left: -19px; }
+.opac-auto-130 { position: relative; left: 80px; }
+.opac-auto-131 { position: relative; top: 0px; left: 55px; }
+.opac-auto-132 { position: relative; top: 13px; }
+.opac-auto-133 { position: relative; top: -13px; left: 2px; font-size: 10px; }
+.opac-auto-134 { position: relative; top: -15px; left: 172px; }
+.opac-auto-135 { position: relative; top: -15px; left: -23px; }
+.opac-auto-136 { position: relative; top: 161px; left: 172px; }
+.opac-auto-137 { position: relative; top: 161px; left: -23px; }
+#home_adv_search_link { position: relative; top: -1px; left: 10px; }
+#util_back_btn { position: relative; top: 1px; left: 10px; }
+.opac-auto-140 { position: relative; top: -2px; }
+#util_help_btn { position: relative; top: 2px; left: 40px; }
+#util_forw_btn { position: relative; top: 2px; left: 50px; }
+.opac-auto-143 { position: relative; top: -3px; }
+#util_home_btn { position: relative; top: 3px; left: 20px; }
+.opac-auto-145 { position: relative; top: -3px; left: 3px; }
+.opac-auto-146 { position: relative; top: -3px; left: -5px; }
+.opac-auto-147 { position: relative; top: -5px; }
+.pos-rel-top-5 { position: relative; top: 5px; }
+.opac-auto-149 { position: relative; top: 5px; left: 25px; }
+#util_print_btn { position: relative; top: 5px; left: 30px; }
+.opac-auto-151 { position: relative; top: 75px; }
+#adv_reset { position: relative; top: -9px; }
+.opac-auto-153 { position: relative; z-index: 100; }
+.text-center { text-align: center; }
+.opac-auto-156 { text-align: center; font-weight: bold; }
+#adv_quick_search_sidebar { text-align: center; margin-top: 20px; width: 400px; }
+.opac-auto-158 { text-align: center; margin-top: 6px; margin-bottom: 6px }
+.opac-auto-159 { text-align: center; padding: 20px; width: 100% }
+.opac-auto-160 { text-align: center; padding-bottom: 8px; }
+.opac-auto-161 { text-align: right; padding-right: 7px; width: 62px; }
+.opac-auto-162 { vertical-align: top; }
+.nowrap { white-space: nowrap; }
+.opac-auto-164 { white-space: nowrap; padding-left: 5px; }
+.full-width { width: 100%; }
+.opac-auto-167 { width: 100%; border: 1px solid black; padding: 6px; margin-top: 5px; }
+.opac-auto-168 { width: 100%; border: 2px solid #E0F0E0; margin-bottom: 20px; }
+.opac-auto-169 { width: 100%; height: 100%; }
+.opac-auto-170 { width: 100%; margin-top: 20px; border-top: 1px dotted #ccc; padding-top: 8px; }
+.opac-auto-171 { font-size: 120%; text-align: center; font-style: italic; }
+.opac-auto-172 { width: 100%; text-align: center; padding-bottom: 5px; }
+.opac-auto-173 { width: 10px; }
+.opac-auto-174 { width: 111px; height: 25px; }
+.opac-auto-175 { width: 125px; height: 21px; }
+.opac-auto-176 { width: 129px; }
+#search_box { width: 162px; }
+.opac-auto-178 { width: 174px; }
+.opac-auto-179 { width: 175px; margin-right: 11px; }
+.opac-auto-179 optgroup { margin-left: 1em; font-weight: normal; font-style: italic; }
+.opac-auto-179-inner-option { margin-left: 2em; } /* XXX ".opac-auto-179 optgroup option" doesn't work!? */
+.opac-auto-180 { width: 182px; color: black; padding: 5px 25px; }
+.opac-auto-181 { width: 195px; }
+.opac-auto-182 { width: 230px; text-align: left; margin-top: 3px; }
+.opac-auto-183 { width: 250px; text-align: left; }
+.opac-auto-184 { width: 26px; height: 23px; margin-top: 6px; margin-bottom: 6px; }
+.opac-auto-185 { width: 324px; }
+.opac-auto-186 { width: 400px; margin-top: 20px; }
+.opac-auto-187 { width: 662px; }
+.opac-auto-188 { width: 700px; height: 30px; border: 1px solid red; }
+.opac-auto-189 { width: 742px; float: left; }
+.opac-auto-190 { width: 88px; }
+.opac-auto-191 { width: 90px; }
+#cn_browse_div > div { width: 90%; text-align: center; margin: 10px; }
+.opac-auto-193 { width: 91px; }
+#cn_browse { width: 95%; text-align: center; padding: 15px; }
+.opac-auto-195 { width: 99%; text-align: center }
+#homesearch_thing { width: 664px; height: 117px; background: #bda964; }
+#mystery_thing { width: 664px; height: 35px; background: #ffffff; }
diff --git a/Open-ILS/web/css/skin/default/opac/style.css b/Open-ILS/web/css/skin/default/opac/style.css
new file mode 100644 (file)
index 0000000..0ce3c8e
--- /dev/null
@@ -0,0 +1,995 @@
+body {
+       margin:0;
+       font-family: Arial, Helvetica, sans-serif;
+       font-size: 12px;
+       background:#333;
+}
+
+img {
+       border: none;
+}
+
+a {
+       color: #003399;
+       text-decoration: none;
+}
+
+a:hover {
+       text-decoration: underline;
+}
+
+#search-wrapper input[type=text] {
+       border:none;
+       margin:0;
+       padding:0;
+}
+
+#search-wrapper select {
+       border:1px solid #e9ebf3;
+       margin:0;
+       padding:0;
+       width:168px;
+}
+
+/*
+#search-wrapper select {
+       border:0px solid black;
+       filter:alpha(opacity=0);
+       -moz-opacity:0;
+       -khtml-opacity:0;
+       opacity:0;
+       padding:0;
+       margin:0;
+       height:18px;
+       font-size: 12px;
+}
+*/
+h1 {
+       margin:0;
+       margin-bottom: 5px;
+       font-size: 20px;
+       font-weight:normal;
+}
+
+h2 {
+       margin:0;
+       margin-bottom: 5px;
+       font-size: 14px;
+       font-weight:bold;
+}
+
+.hide_me, .hidden {
+       display: none;
+       visibility: hidden;
+}
+
+div.select-box-wrapper {
+       position:absolute;
+       padding-top:2px;
+       padding-left:3px;
+       overflow:hidden;
+       text-align:left;
+}
+
+div.select-wrapper {
+       border:1px solid #4C8AB0;
+       display:inline-block;
+       position:relative;
+       z-index:2;
+       background:url('/images/dropdown.gif') no-repeat right center;
+}
+
+div.select-wrapper:hover {
+       background:url('/images/dropdown-hover.gif') no-repeat right center;
+}
+
+#dash_wrapper {
+       width:500px;
+       position:relative;
+       top:-26px;
+}
+
+#dashboard {
+       clear:both;
+       float:right;
+       width:384px;
+}
+
+#dashboard span {
+       font-weight:bold;
+       position:relative;
+       left:-1px;
+}
+
+#dash_user {
+       font-weight: bold;
+       text-transform: capitalize;
+    position: relative;
+    top: 10px;
+}
+
+#dash_corner_mid1a {
+    vertical-align: top;
+    background: url('/images/dash-corner-mid1.png') repeat-x;
+    padding-left: 8px;
+}
+#dash_corner_mid1b {
+    background: url('/images/dash-corner-mid1.png') repeat-x;
+    padding: 0px 8px 0px 10px;
+}
+#dash_corner_mid1b img { position: relative; top: -1px; }
+#dash_corner_mid1c {
+    background: url('/images/dash-corner-mid1.png') repeat-x;
+    vertical-align: top;
+}
+#dash_corner_mid2a {
+    vertical-align: top;
+    width: 372px;
+    background: url('/images/dash-corner-mid2.png') repeat-x;
+}
+.dash-pos-out { position: relative; left: 3px; }
+.dash-pos-holds { position: relative; left: 100px; }
+.dash-align-out { text-align: right; width: 86px; }
+.dash-align-holds { text-align: right; width: 62px; }
+.dash-pos-pickup { position: relative; left: 170px; }
+.dash-align-pickup { text-align: right; width: 111px; }
+.dash-pos-fines { position: relative; left: 284px; }
+.dash-align-fines { text-align: right; width: 76px; }
+.pos-rel-top4 { position: relative; top: 4px; }
+#dash_number_row { position: relative; top: 6px; }
+#logout_link { left: 1px; }
+
+#dash_checked { color: #ffcc33; }
+#dash_holds { color: #ffcc33; }
+#dash_pickup { color: #1dd93c; }
+#dash_fines { color: #f41d36; }
+#header {
+       color: #fff;
+       padding: 26px 0px 26px 0px;
+       width: 974px;
+       margin: auto;
+       font-size:11px;
+}
+
+#header a {
+       color: #fff;
+}
+
+#header a:hover {
+       color: white;
+       text-decoration: none;
+}
+
+#header-links {
+       color: #afafaf;
+       font-size: 11px;
+       font-weight: bold;
+       position: relative;
+       top:4px;
+       
+}
+
+#header-links a {
+       color: #afafaf;
+       display: block;
+       float:left;
+       margin-right:22px;
+}
+
+#header-links a:hover {
+       color: white;
+       text-decoration: none;
+}
+
+#header #header-links2 {
+       position:relative;
+       top:-8px;
+       color: white;
+       padding-bottom: 15px;
+}
+
+#header #header-links2 a {
+       color: white;
+}
+
+#header #header-links2 a:hover {
+       text-decoration: underline;
+}
+
+#header #your-acct-login {
+       padding-top:10px;
+}
+
+#gold-links {
+       margin:auto;
+       width:974px;
+       padding-left:0px;
+}
+
+#gold-links-home {
+       margin:auto;
+       width:694px;
+       padding-left:0px;
+}
+
+#util-bar {
+       margin:auto;
+       width:974px;
+       padding-left:0px;
+       height:0px;
+}
+
+#search-wrapper {
+       border-bottom: 1px solid #e9ebf3;
+       padding-bottom: 5px;
+       background: white;
+}
+
+#search_box_wrapper {
+       border:1px solid #e9ebf3;
+       padding: 1px;
+    padding-left: 3px;
+}
+
+#search-wrapper #breadcrumb {
+       margin-top:0px;
+       font-size: 10px;
+       float:left;
+}
+
+#search-wrapper #search-within {
+       margin-top:10px;
+       float:right;
+       position:relative;
+       left:-173px;
+}
+
+#search-wrapper #breadcrumb a {
+       color: black;
+}
+
+#search-wrapper #search_frm label {
+       font-size: 10px;
+}
+
+#search-wrapper #search-box {
+       width:974px;
+       margin:auto;
+       padding-left: 0px;
+}
+
+#utils {
+       float:right;
+       z-index:1;
+       width:150px;
+       height:30px;
+       background:url('/images/utils-corner-left.png') no-repeat left top;
+       padding-left: 3px;
+       color: white;
+       position:relative;
+}
+
+#utils a {
+       color: white;
+       font-size: 10px;
+}
+#adv_search_tabs {
+       height:33px;
+       width:974px;
+       margin:auto;
+}
+
+#adv_search_tabs a {
+       float: left;
+       display: block;
+       height:33px;
+       margin-right:7px;
+}
+
+#adv_search {
+       width:156px;
+       background:url('/images/adv_search_on.gif') no-repeat bottom;
+}
+
+#num_search {
+       width:156px;
+       background:url('/images/num_search_off.gif') no-repeat bottom;
+}
+
+#expert_search {
+       width:156px;
+       background:url('/images/expert_search_off.gif') no-repeat bottom;
+}
+
+#acct_tabs, #acct_fines_tabs {
+       height:33px;
+       width:974px;
+       margin:auto;
+}
+
+#acct_tabs a, #acct_fines_tabs a {
+       float: left;
+       display: block;
+       height:33px;
+       margin-right:7px;
+}
+
+.acct-tab {
+    background-repeat: no-repeat;
+    background-position: bottom;
+    width:156px;
+}
+
+.acct-main-off {
+       background-image:url('/images/acct_summary_off.gif');
+}
+.acct-main-on {
+       background-image:url('/images/acct_summary_on.gif');
+}
+
+.acct-circs-off {
+       background-image:url('/images/acct_checked_out_off.gif');
+}
+.acct-circs-on {
+       background-image:url('/images/acct_checked_out_on.gif');
+}
+
+.acct-holds-off {
+       background-image:url('/images/acct_holds_off.gif');
+}
+.acct-holds-on {
+       background-image:url('/images/acct_holds_on.gif');
+}
+
+.acct-prefs-off {
+       background-image:url('/images/acct_prefs_off.gif');
+}
+.acct-prefs-on {
+       background-image:url('/images/acct_prefs_on.gif');
+}
+
+.acct-lists-off {
+       background-image:url('/images/acct_lists_off.gif');
+}
+.acct-lists-on {
+       background-image:url('/images/acct_lists_on.gif');
+}
+
+#rdetail_header {
+       font-size:14px;
+       font-weight:bold;
+       color:#074079;
+       padding: 5px 7px 6px 0px;
+       border-bottom: 1px dotted #ccc;
+}
+
+#rdetail_result_count {
+       color: black;
+       font-size: 11px;
+       font-weight: normal;
+}
+
+#rdetail_result_nav {
+       float:right;
+       font-size: 11px;
+       font-weight:normal;
+}
+
+#rdetail_details_table {
+       margin-top: 15px;
+}
+
+#rdetail_title {
+       font-size: 18px;
+}
+
+#rdetail_image { border: none; }
+#rdetail_image_cell {
+       padding-top: 3px;
+       padding-right: 10px;
+}
+
+.rdetail_aux_utils {
+       border-left:1px dotted #ccc;
+       padding-left: 17px;
+       padding-bottom: 6px;
+       padding-right: 70px;
+}
+
+.results_aux_utils {
+       border-left:1px dotted #ccc;
+       padding-left: 17px;
+       padding-bottom: 6px;
+       padding-right: 50px;
+}
+
+#rdetails_status td, #rdetails_status2 td {
+       white-space:nowrap !important;
+       padding: 7px 0px 3px 13px;
+}
+
+#rdetails_status thead td {
+       background-color: #d8d8d8;
+       padding: 13px 0px 13px 13px;
+       font-size: 10px;
+       text-transform: uppercase;
+       font-weight: bold;
+}
+
+#rdetails_status tbody td {
+       padding-left: 13px;;
+}
+
+.rdetail_extras {
+       height: 29px;
+       background: #9ad0f1;
+       padding-top:1px;
+       margin-bottom: 10px;
+       margin-top: 10px;
+       clear:both;
+}
+
+.rdetail_extras_hr {
+       height: 1px;
+       background: #b7def5;
+       margin-left: 1px;
+       margin-right: 1px;
+}
+
+.rdetail_extras_link {
+       padding-top: 4px;
+       padding-left: 12px;
+       font-size: 10px;
+       text-transform: uppercase;
+       font-weight: bold;
+}
+
+.rdetail_extras_lbl {
+       position: relative;
+       top: -4px;
+       left: 7px;
+}
+
+#paginate-homebanner a.toc {
+       display:block;
+       width:20px;
+       height:20px;
+       background:gray;
+       float:left;
+       margin-left:2px;
+       margin-right:2px;
+       margin-top:2px;
+}
+
+#rdetail_extras_expand, #rdetail_extras_collapse, #rdetail_locs_collapse {
+       margin-left: 13px;
+}
+
+#rdetail_locs_expand, #rdetail_locs_collapse {
+       padding-bottom:3px;
+       margin-top:15px;
+       margin-left:13px;
+}
+
+#rdetail_anotes_div .biography {
+       margin:0;
+}
+
+#paginate-homebanner a.selected {
+       border: 2px solid black;
+       margin-top:0px;
+       margin-left:0px;
+       margin-right:0px;
+}
+
+#hp-buttons {
+       margin: auto;
+       margin-top: 6px;
+       width: 694px; /* 974px; */
+}
+
+#hp-welcome {
+       position:absolute;
+       width:295px;
+       height:192px;
+       background: url('/images/banner-bg.png') no-repeat;
+       color: #fff;
+       padding-left: 33px;
+       padding-top: 21px;
+       z-index:9999999999;
+}
+
+#hp-welcome h1 {
+       font-size: 25px;
+       margin-bottom:15px;
+}
+
+#hp-welcome a {
+       color: #fff;
+       text-decoration: underline;
+}
+
+#hp-banner {
+       margin: auto;
+       width: 694px; /* formerly 974px */
+       height: 213px;
+}
+
+#hp-ql-table {
+       margin-left: 2px;
+       padding-top: 3px;
+}
+
+#hp-ql-table a {
+       color: #333;
+       font-weight: bold;
+       font-size: 13px;
+       text-transform: uppercase;
+       text-decoration: none;
+       display: block;
+       width: 144px;
+       height: 25px;
+       padding-top: 9px;
+       padding-left: 15px;
+       background: url('/images/button-bg.png') no-repeat;
+}
+
+#hp-ql-bottom {
+       width: 640px;
+       height: 31px;
+       padding-left: 24px;
+       padding-top: 13px;
+       background: url('/images/hp-links-mid.jpg') repeat-x;
+}
+
+#hp-ql-bottom a {
+       display: inline-block;
+       text-decoration: none;
+       color: white;
+       font-size: 15px;
+       font-weight: bold;
+}
+
+#hp-ql-bottom img {
+    position:relative;
+    top:-1px;
+    left:2px;
+}
+
+.almost-content-wrapper {
+       background: white;
+}
+
+#content-wrapper {
+       background: white;
+       min-height: 260px;
+       border-bottom: 1px solid black;
+}
+
+.content-wrapper-record-page { top: -15px; position: relative; }
+
+#main-content-home { width: 694px; margin: auto; padding-left: 17px; }
+#main-content { width: 974px; margin:auto; padding-left: 0px; }
+
+#main-content .login_boxes {
+       border: 1px solid #dedede;
+       background:url('/images/login-bg.jpg') top repeat-x;
+       color: #333;
+}
+
+#main-content .login_boxes h1 {
+       font-weight: normal;
+       font-size: 25px;
+       margin:0;
+}
+
+#main-content .left_brain {
+       padding-left:28px;
+       padding-top:25px;
+}
+
+#main-content .left_brain input[type=text], #main-content .left_brain input[type=password] {
+       width:167px;
+       height:18px;
+       margin:0;
+       padding:0;
+       border:none;
+       background: none;
+       font-size: 15px;
+       color: #666;
+}
+
+#main-content .left_brain .input_bg {
+       padding:10px 10px 0px 13px;
+       background: url('/images/login-box-bg.jpg') no-repeat;
+       width:167px;
+       height:29px;
+}
+
+#home-buttons-inner {
+       width:664px;
+       height:117px;
+       background:#bda964;
+}
+
+#holds_temp_parent td {
+       border-bottom:1px solid #dcdbdb;
+}
+
+#holds_temp_parent input, #holds_temp_parent select {
+       margin:0;
+}
+
+
+
+
+#results_header_bar {
+       background: #929292;
+       border-top:1px solid #8b8b8b;
+}
+
+#results_header_inner {
+       height:32px;
+       width:974px;
+       margin:auto;
+       padding-top:6px;
+}
+
+.results_header_btns {
+       float:left;
+       margin-right: 6px;
+}
+
+.cached_list_div { width: 111px; height: 25px; }
+
+.results_header_div {
+       float: left;
+       width: 0px;
+       height: 25px;
+       border-left: 1px solid #7c7c7c;
+       border-right: 1px solid #9c9c9c;
+       margin: 0px 13px;
+}
+
+.results_header_lbl {
+       font-weight: bold;
+       float: left;
+       font-size: 11px;
+       color: #191919;
+       position: relative;
+       top: 5px;
+       margin-right: 6px;
+}
+
+.results_header_sel {
+    /* width: 88px; */
+       float:left;
+       position: relative;
+       top: 2px;
+       margin:0;
+}
+
+.results_header_nav1 {
+       padding: 5px 7px 6px 0px;
+       border-bottom: 1px dotted #ccc;
+}
+
+.results_header_nav1 .h1 {
+       font-size:14px;
+       font-weight:bold;
+       color:#074079;
+}
+
+.start_end_links_span {
+       font-size: 11px;
+}
+
+.nav_arrow_fix {
+       font-size:8px;
+       position:relative;
+       top:-1px;
+}
+
+#result_table_div {
+       margin-top: 20px;
+}
+
+.result_numbers {
+       font-size: 11px; padding-left:15px; white-space: nowrap; width: 320px;
+}
+
+.result_table_subtable { width: 100%; border-collapse: collapse; border: 0; }
+
+
+
+
+.icon_text {
+       text-transform:capitalize;
+}
+
+.result_table_title_cell {
+       padding-left: 7px;
+}
+
+#myopac_summary_div p {
+       margin:0;
+       margin-bottom: 10px;
+}
+
+#acct_sum_checked_table td {
+       padding-bottom:5px;
+}
+
+#zero_search_hits div { float:left;width:300px;margin-top:20px; }
+
+#zero_search_hits p {
+       margin-top:0;
+}
+
+#zero_hits_term {
+       text-transform: uppercase;
+    font-weight: bold;
+}
+
+#zero_search_hits #spell_check_link {
+       text-transform: uppercase;
+}
+
+#zero_search_hits #zero_hits_suggestions {
+       text-transform: uppercase;
+}
+
+.results_info_table td {
+       padding-right: 10px;
+}
+
+#myopac_holds_main_table {
+       border-collapse: collapse;
+}
+
+#myopac_holds_main_table td {
+       border: 1px solid black;
+       
+}
+
+#myopac_prefs_div .data_grid {
+       border-collapse:collapse;
+}
+
+#myopac_prefs_div .data_grid td {
+       background:#f0f0f0;
+       border-bottom:3px solid white;
+       padding:6px 0px 7px 17px;
+}
+
+.header_middle {
+       height:22px;
+       font-size:14px;
+       font-weight:bold;
+       color:#074079;
+       padding: 0px 7px 0px 0px;
+       border-bottom: 1px dotted #ccc;
+}
+
+.header_middle a {
+       font-size: 12px;
+       font-weight: normal;
+}
+
+.acct_sum_row {
+       padding: 7px 15px;
+       width: 712px;
+       background: #f0f0f0;
+       margin-bottom: 2px;
+       font-size: 10px;
+       font-weight: bold;
+       text-transform: uppercase;
+}
+
+.acct_sum_row a {
+       text-transform: none;
+       font-size: 12px;
+       position:relative;
+       top:-1px;
+}
+
+.acct_sum_row .view_link {
+       font-weight: normal;
+       font-size:12px;
+}
+
+#myopac_sum_fines {
+       float:right;
+       padding: 15px 0px 0px 23px;
+       background: #f0f0f0;
+       width: 177px;
+       height: 166px;
+}
+
+#myopac_sum_fines_placehold { float: right; width: 177px; height: 166px; }
+
+.acct_holds_temp td {
+       text-align: left;
+}
+
+#acct_checked_tabs .align, #acct_holds_tabs .align, #acct_prefs_tabs .align {
+       float:left;
+       /*padding-left:10px;*/
+}
+
+#acct_checked_tabs .selected, #acct_holds_tabs .selected, #acct_prefs_tabs .selected {
+       /*background:url('/images/gray-arrow.png') left 3px no-repeat;*/
+}
+
+#acct_checked_main_header, #acct_holds_main_header, #acct_checked_hist_header, #acct_list_header, #acct_list_header_anon, #temp_list_holds {
+       font-weight:bold;
+       text-transform:uppercase;
+       font-size: 10px;
+}
+
+#acct_checked_main_header td, #acct_holds_main_header td, #acct_checked_hist_header td, #acct_list_header td, #acct_list_header_anon td, #temp_list_holds td {
+       background: #d8d8d8;
+       padding: 8px 0px 7px 0px;
+}
+
+#acct_list_header select, #acct_list_header_anon select {
+       font-weight:normal;
+       text-transform:none;
+}
+
+#acct_holds_activates_table label {
+       font-weight: bold;
+       font-size: 11px;
+       text-transform:uppercase;
+       padding-right: 5px;
+}
+
+.adv_search_font {
+       font-size: 10px;
+}
+
+.search_catalog_lbl {
+       font-size: 14px;
+}
+
+.lbl1 {
+       font-size:14px;
+       font-weight:bold;
+}
+
+.lbl2 {
+       font-size:10px;
+       font-weight:normal;
+       position:relative;
+       top:3px;
+}
+
+#myopac_tabs, #adv_search_parent, #fines_payments_wrapper {
+       background: #929292;
+       border-top:1px solid #8b8b8b;
+       padding-top:5px;
+       margin-bottom:20px;
+}
+
+#fines_payments_wrapper {
+    padding-left: 5px; 
+    padding-right: 5px;
+}
+
+#myopac_payments_table th { text-align: left; }
+
+#adv_search_parent {
+       margin-bottom:0px;
+}
+
+#myopac_loading {
+       width:100%;
+       text-align:center;
+       padding-top:20px;
+       font-size:16px;
+       font-weight:bold;
+}
+
+.chili_link {
+       width:100px !important;
+       text-align: center !important;
+}
+
+.chili_review div.chili_link div {
+       margin: auto;
+}
+
+/* some facet styling */
+.facetClassContainer { margin: 2px; border: 1px solid #CCC; }
+.facetClassLabelContainer { border: 1px solid #CCC; }
+.facetClassLabel { font-weight: bold; text-align: center; }
+.facetFieldContainer {  }
+.facetFieldLabel { padding-left: 2px; margin-top: 5px; margin-bottom: 5px; font-weight: bold; text-align: left; }
+.extraFacetFieldsWrapper { }
+.toggleExtraFacetFieldsButton { float: right; margin: 0px; padding: 0px; }
+.facetFieldLineCount { display: inline-block; border-right: 1px solid #CCC; color: gray; width: 3em; margin-right: 3px }
+.facetField { border-top: 1px solid #CCC; }
+.facetFields { padding-left: 5px; }
+.facetFieldLineValue { overflow: hidden; text-overflow: ellipsis; }
+
+#footer {
+       padding-top:5px;
+       padding-bottom: 10px;
+       color: white;
+       margin: auto;
+       width: 974px;
+       color: #afafaf;
+       font-size: 11px;
+}
+
+#footer a {
+       color: white;
+       color: #afafaf;
+}
+
+.color_4 {
+       text-transform: uppercase;
+       font-weight: bold;
+       font-size: 10px;
+}
+
+.advanced_div { padding-top: 15px; }
+#adv_global_search select { width: 13em; }
+#adv_global_input_table select { width: 7em; }
+.adv_adv_link { font-size: 8pt; color: red; }
+#acct_prefs_header { float: left; }
+#limit_to_available {
+    float: left; position: relative; top: 2px;
+    left: -2px; margin-right: 4px;
+}
+#rdetail_copy_info_table { font-size: 8pt; }
+#rdetail_copy_info_table td { padding: 3px; }
+.search_page_nav_link { cursor: pointer; }
+#opac.result.sort { width: 160px; }
+.renew-summary { font-size: 125%; font-style: italic; margin: 0.5ex 0; }
+.failure-text { margin-left: 4em; font-style: italic; color: #ff0000; }
+.refine-controls { font-size: 125%; padding: 0.5ex 0; }
+#adv_search_refine input[type=text] { border: 1px inset #ccc !important; }
+#adv_search_refine select { border: 1px inset #ccc !important; }
+#adv_search_refine {
+    padding-left: 5em; background-color: #d7d7d7; margin: 2ex 0;
+}
+.row-remover { position: relative; top: 1px; vertical-align: middle; }
+.subtle-button {
+    background-color: #ffffff;
+    color: #003399; text-decoration: none;
+    font-size: 12px;
+    padding: 0; border: 0; margin: 0;
+    vertical-align: middle;
+}
+.subtle-button:hover { text-decoration: underline; cursor: pointer; }
+.no-dec:hover { text-decoration: none; }
+.pending-addr td { background-color: #ffcccc !important; border: 0 !important; }
+
+#account-update-email table { text-align: center; padding: 20px; margin-top: 30px; border-collapse: collapse; }
+#account-update-email table td { padding: 5px 15px 5px 15px; border-bottom: 1px solid #ddd; text-align: left;}
+#account-update-email-error { font-size: 1.5em; padding: 10px; border:1px solid #e9ebf3;}
+a.dash-link:hover { text-decoration: underline !important; }
+#list_create_table td { vertical-align: middle; padding: 0 8px; }
+#list_create_table {
+    background-color: #ccc;
+    padding-bottom: 4px;
+    margin-bottom: 10px;
+    border-bottom: 1px dotted #666;
+}
+.list-create-table-buttons input[type=image] { margin-top: 2px; }
+.result_table_format_cell { padding: 0px 10px; text-align: center; }
+#hold_editor h1 { font-size: 120%; font-weight: bold; }
+#hold_editor h2 { font-size: 111%; font-weight: normal; text-indent: 2em; font-style: italic; }
+#hold_editor h1, #hold_editor h2 { margin: 2px 0; }
+#hold_editor_table { background-color: #ddd; padding: 0.5em; }
+#hold_editor_table th { text-align: right; padding-right: 1em; }
+#hold_editor_table td { padding: 0.25em 0; }
+.fmt-note { vertical-align: middle; padding-left: 1em !important; }
+.hold-editor-controls { text-align: center; padding-top: 1em !important; }
+.hold-editor-controls a { padding-left: 2em; }
+
+.text-right { text-align: right; }
+.rdetail-author-div { padding-bottom: 10px; }
+
+.invisible { visibility: hidden; }
diff --git a/Open-ILS/web/images/KCLS_logo_horiz.gif b/Open-ILS/web/images/KCLS_logo_horiz.gif
new file mode 100644 (file)
index 0000000..8e1d56e
Binary files /dev/null and b/Open-ILS/web/images/KCLS_logo_horiz.gif differ
diff --git a/Open-ILS/web/images/acct-btn-hover.png b/Open-ILS/web/images/acct-btn-hover.png
new file mode 100644 (file)
index 0000000..1e6e20a
Binary files /dev/null and b/Open-ILS/web/images/acct-btn-hover.png differ
diff --git a/Open-ILS/web/images/acct-btn.png b/Open-ILS/web/images/acct-btn.png
new file mode 100644 (file)
index 0000000..c9b92cd
Binary files /dev/null and b/Open-ILS/web/images/acct-btn.png differ
diff --git a/Open-ILS/web/images/acct_checked_out_off.gif b/Open-ILS/web/images/acct_checked_out_off.gif
new file mode 100644 (file)
index 0000000..dcfcfcb
Binary files /dev/null and b/Open-ILS/web/images/acct_checked_out_off.gif differ
diff --git a/Open-ILS/web/images/acct_checked_out_on.gif b/Open-ILS/web/images/acct_checked_out_on.gif
new file mode 100644 (file)
index 0000000..f364d38
Binary files /dev/null and b/Open-ILS/web/images/acct_checked_out_on.gif differ
diff --git a/Open-ILS/web/images/acct_favs_off.gif b/Open-ILS/web/images/acct_favs_off.gif
new file mode 100644 (file)
index 0000000..5ffc024
Binary files /dev/null and b/Open-ILS/web/images/acct_favs_off.gif differ
diff --git a/Open-ILS/web/images/acct_favs_on.gif b/Open-ILS/web/images/acct_favs_on.gif
new file mode 100644 (file)
index 0000000..f96342a
Binary files /dev/null and b/Open-ILS/web/images/acct_favs_on.gif differ
diff --git a/Open-ILS/web/images/acct_fines_off.jpg b/Open-ILS/web/images/acct_fines_off.jpg
new file mode 100644 (file)
index 0000000..b73b61d
Binary files /dev/null and b/Open-ILS/web/images/acct_fines_off.jpg differ
diff --git a/Open-ILS/web/images/acct_fines_on.jpg b/Open-ILS/web/images/acct_fines_on.jpg
new file mode 100644 (file)
index 0000000..4ea7e89
Binary files /dev/null and b/Open-ILS/web/images/acct_fines_on.jpg differ
diff --git a/Open-ILS/web/images/acct_holds_off.gif b/Open-ILS/web/images/acct_holds_off.gif
new file mode 100644 (file)
index 0000000..6179396
Binary files /dev/null and b/Open-ILS/web/images/acct_holds_off.gif differ
diff --git a/Open-ILS/web/images/acct_holds_on.gif b/Open-ILS/web/images/acct_holds_on.gif
new file mode 100644 (file)
index 0000000..d1c75bb
Binary files /dev/null and b/Open-ILS/web/images/acct_holds_on.gif differ
diff --git a/Open-ILS/web/images/acct_lists_off.gif b/Open-ILS/web/images/acct_lists_off.gif
new file mode 100644 (file)
index 0000000..9a5b2a2
Binary files /dev/null and b/Open-ILS/web/images/acct_lists_off.gif differ
diff --git a/Open-ILS/web/images/acct_lists_on.gif b/Open-ILS/web/images/acct_lists_on.gif
new file mode 100644 (file)
index 0000000..668b0c9
Binary files /dev/null and b/Open-ILS/web/images/acct_lists_on.gif differ
diff --git a/Open-ILS/web/images/acct_payments_off.jpg b/Open-ILS/web/images/acct_payments_off.jpg
new file mode 100644 (file)
index 0000000..c8a50f5
Binary files /dev/null and b/Open-ILS/web/images/acct_payments_off.jpg differ
diff --git a/Open-ILS/web/images/acct_payments_on.jpg b/Open-ILS/web/images/acct_payments_on.jpg
new file mode 100644 (file)
index 0000000..c571398
Binary files /dev/null and b/Open-ILS/web/images/acct_payments_on.jpg differ
diff --git a/Open-ILS/web/images/acct_prefs_off.gif b/Open-ILS/web/images/acct_prefs_off.gif
new file mode 100644 (file)
index 0000000..c357add
Binary files /dev/null and b/Open-ILS/web/images/acct_prefs_off.gif differ
diff --git a/Open-ILS/web/images/acct_prefs_on.gif b/Open-ILS/web/images/acct_prefs_on.gif
new file mode 100644 (file)
index 0000000..67d1f47
Binary files /dev/null and b/Open-ILS/web/images/acct_prefs_on.gif differ
diff --git a/Open-ILS/web/images/acct_sum_fines_bl.png b/Open-ILS/web/images/acct_sum_fines_bl.png
new file mode 100644 (file)
index 0000000..d750579
Binary files /dev/null and b/Open-ILS/web/images/acct_sum_fines_bl.png differ
diff --git a/Open-ILS/web/images/acct_sum_fines_br.png b/Open-ILS/web/images/acct_sum_fines_br.png
new file mode 100644 (file)
index 0000000..8aa81f0
Binary files /dev/null and b/Open-ILS/web/images/acct_sum_fines_br.png differ
diff --git a/Open-ILS/web/images/acct_sum_fines_tl.png b/Open-ILS/web/images/acct_sum_fines_tl.png
new file mode 100644 (file)
index 0000000..17051c9
Binary files /dev/null and b/Open-ILS/web/images/acct_sum_fines_tl.png differ
diff --git a/Open-ILS/web/images/acct_sum_fines_tr.png b/Open-ILS/web/images/acct_sum_fines_tr.png
new file mode 100644 (file)
index 0000000..fb9dac3
Binary files /dev/null and b/Open-ILS/web/images/acct_sum_fines_tr.png differ
diff --git a/Open-ILS/web/images/acct_summary_off.gif b/Open-ILS/web/images/acct_summary_off.gif
new file mode 100644 (file)
index 0000000..63456c1
Binary files /dev/null and b/Open-ILS/web/images/acct_summary_off.gif differ
diff --git a/Open-ILS/web/images/acct_summary_on.gif b/Open-ILS/web/images/acct_summary_on.gif
new file mode 100644 (file)
index 0000000..99d4990
Binary files /dev/null and b/Open-ILS/web/images/acct_summary_on.gif differ
diff --git a/Open-ILS/web/images/add_mylist.gif b/Open-ILS/web/images/add_mylist.gif
new file mode 100644 (file)
index 0000000..a30b32d
Binary files /dev/null and b/Open-ILS/web/images/add_mylist.gif differ
diff --git a/Open-ILS/web/images/add_mylist_sel.gif b/Open-ILS/web/images/add_mylist_sel.gif
new file mode 100644 (file)
index 0000000..0448d21
Binary files /dev/null and b/Open-ILS/web/images/add_mylist_sel.gif differ
diff --git a/Open-ILS/web/images/add_mylist_sel.kcls.gif b/Open-ILS/web/images/add_mylist_sel.kcls.gif
new file mode 100644 (file)
index 0000000..45bd8b6
Binary files /dev/null and b/Open-ILS/web/images/add_mylist_sel.kcls.gif differ
diff --git a/Open-ILS/web/images/add_search_row_btn.gif b/Open-ILS/web/images/add_search_row_btn.gif
new file mode 100644 (file)
index 0000000..a48e68c
Binary files /dev/null and b/Open-ILS/web/images/add_search_row_btn.gif differ
diff --git a/Open-ILS/web/images/adv_row_close_btn.png b/Open-ILS/web/images/adv_row_close_btn.png
new file mode 100644 (file)
index 0000000..edccf37
Binary files /dev/null and b/Open-ILS/web/images/adv_row_close_btn.png differ
diff --git a/Open-ILS/web/images/adv_search.png b/Open-ILS/web/images/adv_search.png
new file mode 100644 (file)
index 0000000..79fb08a
Binary files /dev/null and b/Open-ILS/web/images/adv_search.png differ
diff --git a/Open-ILS/web/images/adv_search_hover.png b/Open-ILS/web/images/adv_search_hover.png
new file mode 100644 (file)
index 0000000..0cb3fe1
Binary files /dev/null and b/Open-ILS/web/images/adv_search_hover.png differ
diff --git a/Open-ILS/web/images/adv_search_off.gif b/Open-ILS/web/images/adv_search_off.gif
new file mode 100644 (file)
index 0000000..a129b93
Binary files /dev/null and b/Open-ILS/web/images/adv_search_off.gif differ
diff --git a/Open-ILS/web/images/adv_search_on.gif b/Open-ILS/web/images/adv_search_on.gif
new file mode 100644 (file)
index 0000000..d0faa4f
Binary files /dev/null and b/Open-ILS/web/images/adv_search_on.gif differ
diff --git a/Open-ILS/web/images/another_search.png b/Open-ILS/web/images/another_search.png
new file mode 100644 (file)
index 0000000..4bcd214
Binary files /dev/null and b/Open-ILS/web/images/another_search.png differ
diff --git a/Open-ILS/web/images/another_search_hover.png b/Open-ILS/web/images/another_search_hover.png
new file mode 100644 (file)
index 0000000..08efaf5
Binary files /dev/null and b/Open-ILS/web/images/another_search_hover.png differ
diff --git a/Open-ILS/web/images/arrow-down.gif b/Open-ILS/web/images/arrow-down.gif
new file mode 100644 (file)
index 0000000..ebf64c4
Binary files /dev/null and b/Open-ILS/web/images/arrow-down.gif differ
diff --git a/Open-ILS/web/images/arrow-right.gif b/Open-ILS/web/images/arrow-right.gif
new file mode 100644 (file)
index 0000000..6c82655
Binary files /dev/null and b/Open-ILS/web/images/arrow-right.gif differ
diff --git a/Open-ILS/web/images/arrow-right.png b/Open-ILS/web/images/arrow-right.png
new file mode 100644 (file)
index 0000000..232a5e4
Binary files /dev/null and b/Open-ILS/web/images/arrow-right.png differ
diff --git a/Open-ILS/web/images/asknow_available.gif b/Open-ILS/web/images/asknow_available.gif
new file mode 100644 (file)
index 0000000..326c8d1
Binary files /dev/null and b/Open-ILS/web/images/asknow_available.gif differ
diff --git a/Open-ILS/web/images/banner-bg.png b/Open-ILS/web/images/banner-bg.png
new file mode 100644 (file)
index 0000000..6d990c5
Binary files /dev/null and b/Open-ILS/web/images/banner-bg.png differ
diff --git a/Open-ILS/web/images/banner1.jpg b/Open-ILS/web/images/banner1.jpg
new file mode 100644 (file)
index 0000000..28eaafc
Binary files /dev/null and b/Open-ILS/web/images/banner1.jpg differ
diff --git a/Open-ILS/web/images/btnCancel.png b/Open-ILS/web/images/btnCancel.png
new file mode 100644 (file)
index 0000000..4cfacaf
Binary files /dev/null and b/Open-ILS/web/images/btnCancel.png differ
diff --git a/Open-ILS/web/images/btnSubmit.png b/Open-ILS/web/images/btnSubmit.png
new file mode 100644 (file)
index 0000000..7a67408
Binary files /dev/null and b/Open-ILS/web/images/btnSubmit.png differ
diff --git a/Open-ILS/web/images/button-bg.png b/Open-ILS/web/images/button-bg.png
new file mode 100644 (file)
index 0000000..38390aa
Binary files /dev/null and b/Open-ILS/web/images/button-bg.png differ
diff --git a/Open-ILS/web/images/cancel_btn.gif b/Open-ILS/web/images/cancel_btn.gif
new file mode 100644 (file)
index 0000000..1cebf59
Binary files /dev/null and b/Open-ILS/web/images/cancel_btn.gif differ
diff --git a/Open-ILS/web/images/cd-small.png b/Open-ILS/web/images/cd-small.png
new file mode 100644 (file)
index 0000000..d2f8fb4
Binary files /dev/null and b/Open-ILS/web/images/cd-small.png differ
diff --git a/Open-ILS/web/images/clipboard.png b/Open-ILS/web/images/clipboard.png
new file mode 100644 (file)
index 0000000..b4bf071
Binary files /dev/null and b/Open-ILS/web/images/clipboard.png differ
diff --git a/Open-ILS/web/images/dash-corner-left1.png b/Open-ILS/web/images/dash-corner-left1.png
new file mode 100644 (file)
index 0000000..9559e8b
Binary files /dev/null and b/Open-ILS/web/images/dash-corner-left1.png differ
diff --git a/Open-ILS/web/images/dash-corner-left2.png b/Open-ILS/web/images/dash-corner-left2.png
new file mode 100644 (file)
index 0000000..5bc8112
Binary files /dev/null and b/Open-ILS/web/images/dash-corner-left2.png differ
diff --git a/Open-ILS/web/images/dash-corner-mid1.png b/Open-ILS/web/images/dash-corner-mid1.png
new file mode 100644 (file)
index 0000000..546b8a8
Binary files /dev/null and b/Open-ILS/web/images/dash-corner-mid1.png differ
diff --git a/Open-ILS/web/images/dash-corner-mid2.png b/Open-ILS/web/images/dash-corner-mid2.png
new file mode 100644 (file)
index 0000000..15af112
Binary files /dev/null and b/Open-ILS/web/images/dash-corner-mid2.png differ
diff --git a/Open-ILS/web/images/dash-corner-right1.png b/Open-ILS/web/images/dash-corner-right1.png
new file mode 100644 (file)
index 0000000..061afc9
Binary files /dev/null and b/Open-ILS/web/images/dash-corner-right1.png differ
diff --git a/Open-ILS/web/images/dash-corner-right2.png b/Open-ILS/web/images/dash-corner-right2.png
new file mode 100644 (file)
index 0000000..8663e0c
Binary files /dev/null and b/Open-ILS/web/images/dash-corner-right2.png differ
diff --git a/Open-ILS/web/images/dash-divider.jpg b/Open-ILS/web/images/dash-divider.jpg
new file mode 100644 (file)
index 0000000..19dda7d
Binary files /dev/null and b/Open-ILS/web/images/dash-divider.jpg differ
diff --git a/Open-ILS/web/images/dropdown-hover.gif b/Open-ILS/web/images/dropdown-hover.gif
new file mode 100644 (file)
index 0000000..1ac62ae
Binary files /dev/null and b/Open-ILS/web/images/dropdown-hover.gif differ
diff --git a/Open-ILS/web/images/dropdown.gif b/Open-ILS/web/images/dropdown.gif
new file mode 100644 (file)
index 0000000..3aab6fe
Binary files /dev/null and b/Open-ILS/web/images/dropdown.gif differ
diff --git a/Open-ILS/web/images/expert_search_off.gif b/Open-ILS/web/images/expert_search_off.gif
new file mode 100644 (file)
index 0000000..96b4f51
Binary files /dev/null and b/Open-ILS/web/images/expert_search_off.gif differ
diff --git a/Open-ILS/web/images/expert_search_on.gif b/Open-ILS/web/images/expert_search_on.gif
new file mode 100644 (file)
index 0000000..6a41861
Binary files /dev/null and b/Open-ILS/web/images/expert_search_on.gif differ
diff --git a/Open-ILS/web/images/faqs-btn.png b/Open-ILS/web/images/faqs-btn.png
new file mode 100644 (file)
index 0000000..38134ec
Binary files /dev/null and b/Open-ILS/web/images/faqs-btn.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/a.png b/Open-ILS/web/images/format_icons/item_type/a.png
new file mode 100644 (file)
index 0000000..2800684
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/a.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/c.png b/Open-ILS/web/images/format_icons/item_type/c.png
new file mode 100644 (file)
index 0000000..132ca40
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/c.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/d.png b/Open-ILS/web/images/format_icons/item_type/d.png
new file mode 100644 (file)
index 0000000..132ca40
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/d.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/e.png b/Open-ILS/web/images/format_icons/item_type/e.png
new file mode 100644 (file)
index 0000000..f9f8047
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/e.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/f.png b/Open-ILS/web/images/format_icons/item_type/f.png
new file mode 100644 (file)
index 0000000..f9f8047
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/f.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/g.png b/Open-ILS/web/images/format_icons/item_type/g.png
new file mode 100644 (file)
index 0000000..dd0a56f
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/g.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/i.png b/Open-ILS/web/images/format_icons/item_type/i.png
new file mode 100644 (file)
index 0000000..b6ddf3e
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/i.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/j.png b/Open-ILS/web/images/format_icons/item_type/j.png
new file mode 100644 (file)
index 0000000..5ada234
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/j.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/k.png b/Open-ILS/web/images/format_icons/item_type/k.png
new file mode 100644 (file)
index 0000000..e523300
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/k.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/m.png b/Open-ILS/web/images/format_icons/item_type/m.png
new file mode 100644 (file)
index 0000000..a347513
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/m.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/o.png b/Open-ILS/web/images/format_icons/item_type/o.png
new file mode 100644 (file)
index 0000000..f7b5c7b
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/o.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/p.png b/Open-ILS/web/images/format_icons/item_type/p.png
new file mode 100644 (file)
index 0000000..f7b5c7b
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/p.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/r.png b/Open-ILS/web/images/format_icons/item_type/r.png
new file mode 100644 (file)
index 0000000..7b76d03
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/r.png differ
diff --git a/Open-ILS/web/images/format_icons/item_type/t.png b/Open-ILS/web/images/format_icons/item_type/t.png
new file mode 100644 (file)
index 0000000..2800684
Binary files /dev/null and b/Open-ILS/web/images/format_icons/item_type/t.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/2.png b/Open-ILS/web/images/format_icons/mattype/2.png
new file mode 100644 (file)
index 0000000..b874f44
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/2.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/5.png b/Open-ILS/web/images/format_icons/mattype/5.png
new file mode 100644 (file)
index 0000000..dba509d
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/5.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/a.png b/Open-ILS/web/images/format_icons/mattype/a.png
new file mode 100644 (file)
index 0000000..57ee12c
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/a.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/b.png b/Open-ILS/web/images/format_icons/mattype/b.png
new file mode 100644 (file)
index 0000000..c227660
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/b.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/c.png b/Open-ILS/web/images/format_icons/mattype/c.png
new file mode 100644 (file)
index 0000000..26f4818
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/c.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/d.png b/Open-ILS/web/images/format_icons/mattype/d.png
new file mode 100644 (file)
index 0000000..9f4b0f9
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/d.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/e.png b/Open-ILS/web/images/format_icons/mattype/e.png
new file mode 100644 (file)
index 0000000..96d0eed
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/e.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/f.png b/Open-ILS/web/images/format_icons/mattype/f.png
new file mode 100644 (file)
index 0000000..dcfd893
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/f.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/h.png b/Open-ILS/web/images/format_icons/mattype/h.png
new file mode 100644 (file)
index 0000000..8afcef9
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/h.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/i.png b/Open-ILS/web/images/format_icons/mattype/i.png
new file mode 100644 (file)
index 0000000..f36fe75
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/i.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/j.png b/Open-ILS/web/images/format_icons/mattype/j.png
new file mode 100644 (file)
index 0000000..84cc188
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/j.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/k.png b/Open-ILS/web/images/format_icons/mattype/k.png
new file mode 100644 (file)
index 0000000..96a9f35
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/k.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/l.png b/Open-ILS/web/images/format_icons/mattype/l.png
new file mode 100644 (file)
index 0000000..4ba36f1
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/l.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/m.png b/Open-ILS/web/images/format_icons/mattype/m.png
new file mode 100644 (file)
index 0000000..95e6652
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/m.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_downloadableebook.png b/Open-ILS/web/images/format_icons/mattype/media_downloadableebook.png
new file mode 100644 (file)
index 0000000..82f66ba
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_downloadableebook.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_electronicgames.png b/Open-ILS/web/images/format_icons/mattype/media_electronicgames.png
new file mode 100644 (file)
index 0000000..b696a7a
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_electronicgames.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_evideo.png b/Open-ILS/web/images/format_icons/mattype/media_evideo.png
new file mode 100644 (file)
index 0000000..09a7ea6
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_evideo.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_onlinejournal.png b/Open-ILS/web/images/format_icons/mattype/media_onlinejournal.png
new file mode 100644 (file)
index 0000000..65cac4c
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_onlinejournal.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_player.png b/Open-ILS/web/images/format_icons/mattype/media_player.png
new file mode 100644 (file)
index 0000000..64197e1
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_player.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_podcasts.png b/Open-ILS/web/images/format_icons/mattype/media_podcasts.png
new file mode 100644 (file)
index 0000000..d563fbb
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_podcasts.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_streamingaudio.png b/Open-ILS/web/images/format_icons/mattype/media_streamingaudio.png
new file mode 100644 (file)
index 0000000..51c31c3
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_streamingaudio.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_streamingvideo.png b/Open-ILS/web/images/format_icons/mattype/media_streamingvideo.png
new file mode 100644 (file)
index 0000000..3fe2cbe
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_streamingvideo.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/media_vhs.png b/Open-ILS/web/images/format_icons/mattype/media_vhs.png
new file mode 100644 (file)
index 0000000..11c1e42
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/media_vhs.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/n.png b/Open-ILS/web/images/format_icons/mattype/n.png
new file mode 100644 (file)
index 0000000..62b1af2
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/n.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/o.png b/Open-ILS/web/images/format_icons/mattype/o.png
new file mode 100644 (file)
index 0000000..c60d039
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/o.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/p.png b/Open-ILS/web/images/format_icons/mattype/p.png
new file mode 100644 (file)
index 0000000..009d292
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/p.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/q.png b/Open-ILS/web/images/format_icons/mattype/q.png
new file mode 100644 (file)
index 0000000..0949630
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/q.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/r.png b/Open-ILS/web/images/format_icons/mattype/r.png
new file mode 100644 (file)
index 0000000..65a2de2
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/r.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/s.png b/Open-ILS/web/images/format_icons/mattype/s.png
new file mode 100644 (file)
index 0000000..94cebfb
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/s.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/t.png b/Open-ILS/web/images/format_icons/mattype/t.png
new file mode 100644 (file)
index 0000000..437f91f
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/t.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/v.png b/Open-ILS/web/images/format_icons/mattype/v.png
new file mode 100644 (file)
index 0000000..53a192e
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/v.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/w.png b/Open-ILS/web/images/format_icons/mattype/w.png
new file mode 100644 (file)
index 0000000..1270685
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/w.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/x.png b/Open-ILS/web/images/format_icons/mattype/x.png
new file mode 100644 (file)
index 0000000..bcd621c
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/x.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/y.png b/Open-ILS/web/images/format_icons/mattype/y.png
new file mode 100644 (file)
index 0000000..a5db067
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/y.png differ
diff --git a/Open-ILS/web/images/format_icons/mattype/z.png b/Open-ILS/web/images/format_icons/mattype/z.png
new file mode 100644 (file)
index 0000000..ccf1fed
Binary files /dev/null and b/Open-ILS/web/images/format_icons/mattype/z.png differ
diff --git a/Open-ILS/web/images/go-btn-hover.png b/Open-ILS/web/images/go-btn-hover.png
new file mode 100644 (file)
index 0000000..9b878b2
Binary files /dev/null and b/Open-ILS/web/images/go-btn-hover.png differ
diff --git a/Open-ILS/web/images/go-btn.png b/Open-ILS/web/images/go-btn.png
new file mode 100644 (file)
index 0000000..24091c9
Binary files /dev/null and b/Open-ILS/web/images/go-btn.png differ
diff --git a/Open-ILS/web/images/go_but_long.gif b/Open-ILS/web/images/go_but_long.gif
new file mode 100644 (file)
index 0000000..79d2f9a
Binary files /dev/null and b/Open-ILS/web/images/go_but_long.gif differ
diff --git a/Open-ILS/web/images/golive.jpg b/Open-ILS/web/images/golive.jpg
new file mode 100644 (file)
index 0000000..8b34912
Binary files /dev/null and b/Open-ILS/web/images/golive.jpg differ
diff --git a/Open-ILS/web/images/gray-arrow.png b/Open-ILS/web/images/gray-arrow.png
new file mode 100644 (file)
index 0000000..bf56b6e
Binary files /dev/null and b/Open-ILS/web/images/gray-arrow.png differ
diff --git a/Open-ILS/web/images/green_check.png b/Open-ILS/web/images/green_check.png
new file mode 100644 (file)
index 0000000..9738bd8
Binary files /dev/null and b/Open-ILS/web/images/green_check.png differ
diff --git a/Open-ILS/web/images/header_left.gif b/Open-ILS/web/images/header_left.gif
new file mode 100644 (file)
index 0000000..9543795
Binary files /dev/null and b/Open-ILS/web/images/header_left.gif differ
diff --git a/Open-ILS/web/images/header_right.gif b/Open-ILS/web/images/header_right.gif
new file mode 100644 (file)
index 0000000..f00ff76
Binary files /dev/null and b/Open-ILS/web/images/header_right.gif differ
diff --git a/Open-ILS/web/images/hp-links-left.jpg b/Open-ILS/web/images/hp-links-left.jpg
new file mode 100644 (file)
index 0000000..0b8c9cf
Binary files /dev/null and b/Open-ILS/web/images/hp-links-left.jpg differ
diff --git a/Open-ILS/web/images/hp-links-mid.jpg b/Open-ILS/web/images/hp-links-mid.jpg
new file mode 100644 (file)
index 0000000..c9cdabf
Binary files /dev/null and b/Open-ILS/web/images/hp-links-mid.jpg differ
diff --git a/Open-ILS/web/images/hp-links-right.jpg b/Open-ILS/web/images/hp-links-right.jpg
new file mode 100644 (file)
index 0000000..63812f9
Binary files /dev/null and b/Open-ILS/web/images/hp-links-right.jpg differ
diff --git a/Open-ILS/web/images/locations.jpg b/Open-ILS/web/images/locations.jpg
new file mode 100644 (file)
index 0000000..56e7785
Binary files /dev/null and b/Open-ILS/web/images/locations.jpg differ
diff --git a/Open-ILS/web/images/login-bg.jpg b/Open-ILS/web/images/login-bg.jpg
new file mode 100644 (file)
index 0000000..46fc85f
Binary files /dev/null and b/Open-ILS/web/images/login-bg.jpg differ
diff --git a/Open-ILS/web/images/login-bg2.jpg b/Open-ILS/web/images/login-bg2.jpg
new file mode 100644 (file)
index 0000000..2c38853
Binary files /dev/null and b/Open-ILS/web/images/login-bg2.jpg differ
diff --git a/Open-ILS/web/images/login-box-bg.jpg b/Open-ILS/web/images/login-box-bg.jpg
new file mode 100644 (file)
index 0000000..caf036d
Binary files /dev/null and b/Open-ILS/web/images/login-box-bg.jpg differ
diff --git a/Open-ILS/web/images/login-btn-hover.png b/Open-ILS/web/images/login-btn-hover.png
new file mode 100644 (file)
index 0000000..442f33f
Binary files /dev/null and b/Open-ILS/web/images/login-btn-hover.png differ
diff --git a/Open-ILS/web/images/login-btn.gif b/Open-ILS/web/images/login-btn.gif
new file mode 100644 (file)
index 0000000..69d6a56
Binary files /dev/null and b/Open-ILS/web/images/login-btn.gif differ
diff --git a/Open-ILS/web/images/login-btn.png b/Open-ILS/web/images/login-btn.png
new file mode 100644 (file)
index 0000000..5548b99
Binary files /dev/null and b/Open-ILS/web/images/login-btn.png differ
diff --git a/Open-ILS/web/images/login-btn2.png b/Open-ILS/web/images/login-btn2.png
new file mode 100644 (file)
index 0000000..ff4af14
Binary files /dev/null and b/Open-ILS/web/images/login-btn2.png differ
diff --git a/Open-ILS/web/images/logout-btn-hover.png b/Open-ILS/web/images/logout-btn-hover.png
new file mode 100644 (file)
index 0000000..411fc01
Binary files /dev/null and b/Open-ILS/web/images/logout-btn-hover.png differ
diff --git a/Open-ILS/web/images/logout-btn.png b/Open-ILS/web/images/logout-btn.png
new file mode 100644 (file)
index 0000000..bd31a47
Binary files /dev/null and b/Open-ILS/web/images/logout-btn.png differ
diff --git a/Open-ILS/web/images/num_search_off.gif b/Open-ILS/web/images/num_search_off.gif
new file mode 100644 (file)
index 0000000..1062802
Binary files /dev/null and b/Open-ILS/web/images/num_search_off.gif differ
diff --git a/Open-ILS/web/images/num_search_on.gif b/Open-ILS/web/images/num_search_on.gif
new file mode 100644 (file)
index 0000000..f7d7829
Binary files /dev/null and b/Open-ILS/web/images/num_search_on.gif differ
diff --git a/Open-ILS/web/images/one_land.gif b/Open-ILS/web/images/one_land.gif
new file mode 100644 (file)
index 0000000..082b996
Binary files /dev/null and b/Open-ILS/web/images/one_land.gif differ
diff --git a/Open-ILS/web/images/pay-fines-btn-hover.png b/Open-ILS/web/images/pay-fines-btn-hover.png
new file mode 100644 (file)
index 0000000..b7708da
Binary files /dev/null and b/Open-ILS/web/images/pay-fines-btn-hover.png differ
diff --git a/Open-ILS/web/images/pay-fines-btn.png b/Open-ILS/web/images/pay-fines-btn.png
new file mode 100644 (file)
index 0000000..356433b
Binary files /dev/null and b/Open-ILS/web/images/pay-fines-btn.png differ
diff --git a/Open-ILS/web/images/pay_fines_btn.gif b/Open-ILS/web/images/pay_fines_btn.gif
new file mode 100644 (file)
index 0000000..eb4816f
Binary files /dev/null and b/Open-ILS/web/images/pay_fines_btn.gif differ
diff --git a/Open-ILS/web/images/place_hold.gif b/Open-ILS/web/images/place_hold.gif
new file mode 100644 (file)
index 0000000..3f72215
Binary files /dev/null and b/Open-ILS/web/images/place_hold.gif differ
diff --git a/Open-ILS/web/images/plus_sign.png b/Open-ILS/web/images/plus_sign.png
new file mode 100644 (file)
index 0000000..a17d58a
Binary files /dev/null and b/Open-ILS/web/images/plus_sign.png differ
diff --git a/Open-ILS/web/images/projectedmedia.jpg b/Open-ILS/web/images/projectedmedia.jpg
new file mode 100644 (file)
index 0000000..ba0e6d2
Binary files /dev/null and b/Open-ILS/web/images/projectedmedia.jpg differ
diff --git a/Open-ILS/web/images/question-mark.png b/Open-ILS/web/images/question-mark.png
new file mode 100644 (file)
index 0000000..b5f0f87
Binary files /dev/null and b/Open-ILS/web/images/question-mark.png differ
diff --git a/Open-ILS/web/images/questions.png b/Open-ILS/web/images/questions.png
new file mode 100644 (file)
index 0000000..9be69b2
Binary files /dev/null and b/Open-ILS/web/images/questions.png differ
diff --git a/Open-ILS/web/images/rdetail_arrow.png b/Open-ILS/web/images/rdetail_arrow.png
new file mode 100644 (file)
index 0000000..e464bf2
Binary files /dev/null and b/Open-ILS/web/images/rdetail_arrow.png differ
diff --git a/Open-ILS/web/images/reset_form_btn.gif b/Open-ILS/web/images/reset_form_btn.gif
new file mode 100644 (file)
index 0000000..6b70964
Binary files /dev/null and b/Open-ILS/web/images/reset_form_btn.gif differ
diff --git a/Open-ILS/web/images/reviews.gif b/Open-ILS/web/images/reviews.gif
new file mode 100644 (file)
index 0000000..b78fa25
Binary files /dev/null and b/Open-ILS/web/images/reviews.gif differ
diff --git a/Open-ILS/web/images/save-btn.png b/Open-ILS/web/images/save-btn.png
new file mode 100644 (file)
index 0000000..4565850
Binary files /dev/null and b/Open-ILS/web/images/save-btn.png differ
diff --git a/Open-ILS/web/images/save_btn.gif b/Open-ILS/web/images/save_btn.gif
new file mode 100644 (file)
index 0000000..f87282a
Binary files /dev/null and b/Open-ILS/web/images/save_btn.gif differ
diff --git a/Open-ILS/web/images/search_btn.gif b/Open-ILS/web/images/search_btn.gif
new file mode 100644 (file)
index 0000000..f2fdc9b
Binary files /dev/null and b/Open-ILS/web/images/search_btn.gif differ
diff --git a/Open-ILS/web/images/small-rss.png b/Open-ILS/web/images/small-rss.png
new file mode 100644 (file)
index 0000000..67d0f37
Binary files /dev/null and b/Open-ILS/web/images/small-rss.png differ
diff --git a/Open-ILS/web/images/starz.png b/Open-ILS/web/images/starz.png
new file mode 100644 (file)
index 0000000..4a79dd4
Binary files /dev/null and b/Open-ILS/web/images/starz.png differ
diff --git a/Open-ILS/web/images/sub_checked_hist_off.jpg b/Open-ILS/web/images/sub_checked_hist_off.jpg
new file mode 100644 (file)
index 0000000..7fda1c3
Binary files /dev/null and b/Open-ILS/web/images/sub_checked_hist_off.jpg differ
diff --git a/Open-ILS/web/images/sub_checked_hist_on.jpg b/Open-ILS/web/images/sub_checked_hist_on.jpg
new file mode 100644 (file)
index 0000000..703aac1
Binary files /dev/null and b/Open-ILS/web/images/sub_checked_hist_on.jpg differ
diff --git a/Open-ILS/web/images/sub_checked_out_off.jpg b/Open-ILS/web/images/sub_checked_out_off.jpg
new file mode 100644 (file)
index 0000000..0573fbd
Binary files /dev/null and b/Open-ILS/web/images/sub_checked_out_off.jpg differ
diff --git a/Open-ILS/web/images/sub_checked_out_on.jpg b/Open-ILS/web/images/sub_checked_out_on.jpg
new file mode 100644 (file)
index 0000000..97bb178
Binary files /dev/null and b/Open-ILS/web/images/sub_checked_out_on.jpg differ
diff --git a/Open-ILS/web/images/sub_holds_hist_off.jpg b/Open-ILS/web/images/sub_holds_hist_off.jpg
new file mode 100644 (file)
index 0000000..020abe9
Binary files /dev/null and b/Open-ILS/web/images/sub_holds_hist_off.jpg differ
diff --git a/Open-ILS/web/images/sub_holds_hist_on.jpg b/Open-ILS/web/images/sub_holds_hist_on.jpg
new file mode 100644 (file)
index 0000000..020abe9
Binary files /dev/null and b/Open-ILS/web/images/sub_holds_hist_on.jpg differ
diff --git a/Open-ILS/web/images/sub_holds_off.jpg b/Open-ILS/web/images/sub_holds_off.jpg
new file mode 100644 (file)
index 0000000..b888359
Binary files /dev/null and b/Open-ILS/web/images/sub_holds_off.jpg differ
diff --git a/Open-ILS/web/images/sub_holds_on.jpg b/Open-ILS/web/images/sub_holds_on.jpg
new file mode 100644 (file)
index 0000000..9505638
Binary files /dev/null and b/Open-ILS/web/images/sub_holds_on.jpg differ
diff --git a/Open-ILS/web/images/sub_prefs_info_off.jpg b/Open-ILS/web/images/sub_prefs_info_off.jpg
new file mode 100644 (file)
index 0000000..896e227
Binary files /dev/null and b/Open-ILS/web/images/sub_prefs_info_off.jpg differ
diff --git a/Open-ILS/web/images/sub_prefs_info_on.jpg b/Open-ILS/web/images/sub_prefs_info_on.jpg
new file mode 100644 (file)
index 0000000..0895969
Binary files /dev/null and b/Open-ILS/web/images/sub_prefs_info_on.jpg differ
diff --git a/Open-ILS/web/images/sub_prefs_notify_off.jpg b/Open-ILS/web/images/sub_prefs_notify_off.jpg
new file mode 100644 (file)
index 0000000..55df9da
Binary files /dev/null and b/Open-ILS/web/images/sub_prefs_notify_off.jpg differ
diff --git a/Open-ILS/web/images/sub_prefs_notify_on.jpg b/Open-ILS/web/images/sub_prefs_notify_on.jpg
new file mode 100644 (file)
index 0000000..fd536a8
Binary files /dev/null and b/Open-ILS/web/images/sub_prefs_notify_on.jpg differ
diff --git a/Open-ILS/web/images/sub_prefs_search_off.jpg b/Open-ILS/web/images/sub_prefs_search_off.jpg
new file mode 100644 (file)
index 0000000..89115f6
Binary files /dev/null and b/Open-ILS/web/images/sub_prefs_search_off.jpg differ
diff --git a/Open-ILS/web/images/sub_prefs_search_on.jpg b/Open-ILS/web/images/sub_prefs_search_on.jpg
new file mode 100644 (file)
index 0000000..3eab9fa
Binary files /dev/null and b/Open-ILS/web/images/sub_prefs_search_on.jpg differ
diff --git a/Open-ILS/web/images/submit_btn.gif b/Open-ILS/web/images/submit_btn.gif
new file mode 100644 (file)
index 0000000..5286943
Binary files /dev/null and b/Open-ILS/web/images/submit_btn.gif differ
diff --git a/Open-ILS/web/images/tool_back.gif b/Open-ILS/web/images/tool_back.gif
new file mode 100644 (file)
index 0000000..37d1278
Binary files /dev/null and b/Open-ILS/web/images/tool_back.gif differ
diff --git a/Open-ILS/web/images/tool_back.png b/Open-ILS/web/images/tool_back.png
new file mode 100644 (file)
index 0000000..41a13e2
Binary files /dev/null and b/Open-ILS/web/images/tool_back.png differ
diff --git a/Open-ILS/web/images/tool_font.gif b/Open-ILS/web/images/tool_font.gif
new file mode 100644 (file)
index 0000000..9dc10a9
Binary files /dev/null and b/Open-ILS/web/images/tool_font.gif differ
diff --git a/Open-ILS/web/images/tool_forward.gif b/Open-ILS/web/images/tool_forward.gif
new file mode 100644 (file)
index 0000000..db0d800
Binary files /dev/null and b/Open-ILS/web/images/tool_forward.gif differ
diff --git a/Open-ILS/web/images/tool_forward.png b/Open-ILS/web/images/tool_forward.png
new file mode 100644 (file)
index 0000000..582a6b9
Binary files /dev/null and b/Open-ILS/web/images/tool_forward.png differ
diff --git a/Open-ILS/web/images/tool_help.gif b/Open-ILS/web/images/tool_help.gif
new file mode 100644 (file)
index 0000000..2a3de86
Binary files /dev/null and b/Open-ILS/web/images/tool_help.gif differ
diff --git a/Open-ILS/web/images/tool_help.png b/Open-ILS/web/images/tool_help.png
new file mode 100644 (file)
index 0000000..3007c20
Binary files /dev/null and b/Open-ILS/web/images/tool_help.png differ
diff --git a/Open-ILS/web/images/tool_home.gif b/Open-ILS/web/images/tool_home.gif
new file mode 100644 (file)
index 0000000..9b83ccf
Binary files /dev/null and b/Open-ILS/web/images/tool_home.gif differ
diff --git a/Open-ILS/web/images/tool_home.png b/Open-ILS/web/images/tool_home.png
new file mode 100644 (file)
index 0000000..0620200
Binary files /dev/null and b/Open-ILS/web/images/tool_home.png differ
diff --git a/Open-ILS/web/images/tool_mail.gif b/Open-ILS/web/images/tool_mail.gif
new file mode 100644 (file)
index 0000000..83c3573
Binary files /dev/null and b/Open-ILS/web/images/tool_mail.gif differ
diff --git a/Open-ILS/web/images/tool_print.gif b/Open-ILS/web/images/tool_print.gif
new file mode 100644 (file)
index 0000000..d3d7ee3
Binary files /dev/null and b/Open-ILS/web/images/tool_print.gif differ
diff --git a/Open-ILS/web/images/tool_print.png b/Open-ILS/web/images/tool_print.png
new file mode 100644 (file)
index 0000000..2c0dc0b
Binary files /dev/null and b/Open-ILS/web/images/tool_print.png differ
diff --git a/Open-ILS/web/images/utils-corner-left.png b/Open-ILS/web/images/utils-corner-left.png
new file mode 100644 (file)
index 0000000..db70a75
Binary files /dev/null and b/Open-ILS/web/images/utils-corner-left.png differ
diff --git a/Open-ILS/web/images/utils-corner-mid.png b/Open-ILS/web/images/utils-corner-mid.png
new file mode 100644 (file)
index 0000000..80d4857
Binary files /dev/null and b/Open-ILS/web/images/utils-corner-mid.png differ
diff --git a/Open-ILS/web/images/utils-corner-right.jpg b/Open-ILS/web/images/utils-corner-right.jpg
new file mode 100644 (file)
index 0000000..1559897
Binary files /dev/null and b/Open-ILS/web/images/utils-corner-right.jpg differ
diff --git a/Open-ILS/web/images/utils-corner-right.png b/Open-ILS/web/images/utils-corner-right.png
new file mode 100644 (file)
index 0000000..303ab75
Binary files /dev/null and b/Open-ILS/web/images/utils-corner-right.png differ
diff --git a/Open-ILS/web/images/utils-corner.jpg b/Open-ILS/web/images/utils-corner.jpg
new file mode 100644 (file)
index 0000000..4932a28
Binary files /dev/null and b/Open-ILS/web/images/utils-corner.jpg differ
diff --git a/Open-ILS/web/images/view_my_list.png b/Open-ILS/web/images/view_my_list.png
new file mode 100644 (file)
index 0000000..d5f1b83
Binary files /dev/null and b/Open-ILS/web/images/view_my_list.png differ
diff --git a/Open-ILS/web/images/view_my_list_hover.png b/Open-ILS/web/images/view_my_list_hover.png
new file mode 100644 (file)
index 0000000..369cb1a
Binary files /dev/null and b/Open-ILS/web/images/view_my_list_hover.png differ
diff --git a/Open-ILS/web/js/ui/default/opac/simple.js b/Open-ILS/web/js/ui/default/opac/simple.js
new file mode 100644 (file)
index 0000000..776dfef
--- /dev/null
@@ -0,0 +1,29 @@
+/* Keep this dead simple. No dojo. */
+function $(s) { return document.getElementById(s); }
+function removeClass(node, cls) {
+    if (!node || !node.className) return;
+    node.className =
+        node.className.replace(new RegExp("\\b" + cls + "\\b", "g"), "");
+}
+function addClass(node, cls) {
+    if (!node) return;
+    removeClass(node, cls);
+    if (!node.className) node.className = cls;
+    else node.className += ' ' + cls;
+}
+function unHideMe(node) { removeClass(node, "hide_me"); }
+function hideMe(node) { addClass(node, "hide_me"); }
+
+var _search_row_template;
+function addSearchRow() {
+    if (!_search_row_template) {
+        t = $("adv_global_row").cloneNode(true);
+        t.id = null;
+        _search_row_template = t;
+    }
+
+    $("adv_global_tbody").insertBefore(
+        _search_row_template.cloneNode(true),
+        $("adv_global_addrow")
+    );
+}
diff --git a/Open-ILS/web/js/ui/default/opac/staff.js b/Open-ILS/web/js/ui/default/opac/staff.js
new file mode 100644 (file)
index 0000000..abb8ce8
--- /dev/null
@@ -0,0 +1,22 @@
+/* staff client integration functions */
+function debug(msg){dump(msg+'\n')}
+var eventCache={};
+function attachEvt(scope, name, action) {
+    if(!eventCache[scope]) eventCache[scope] = {};
+    if(!eventCache[scope][name]) eventCache[scope][name] = [];
+    eventCache[scope][name].push(action);
+}
+function runEvt(scope, name) {
+    debug('running event '+scope+':'+name);
+    var args = Array.prototype.slice.call(arguments).slice(2);
+    if(eventCache[scope]) {
+        var evt = eventCache[scope][name];
+        for(var i in evt) {evt[i].apply(evt[i], args);}
+    } 
+}
+window.onload = function() {
+    // record details page events
+    var rec = location.href.match(/\/opac\/record\/(\d+)/);
+    if(rec && rec[1]) { runEvt('rdetail', 'recordRetrieved', rec[1]); }
+    // fire other events the staff client is expecting...
+}
diff --git a/Open-ILS/web/templates/default/opac-poc/base.tt2 b/Open-ILS/web/templates/default/opac-poc/base.tt2
new file mode 100644 (file)
index 0000000..6d54607
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns='http://www.w3.org/1999/xhtml' lang='[% ctx.locale %]' xml:lang='[% ctx.locale %]'>
+    <head>
+        <title>[% ctx.page_title %]</title>
+        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+        [% BLOCK html_head; END; # provide a default that can be overridden %]
+        [% PROCESS html_head %]
+    </head>
+    <body>
+        [% content %] 
+    </body>
+</html>
diff --git a/Open-ILS/web/templates/default/opac-poc/common.tt2 b/Open-ILS/web/templates/default/opac-poc/common.tt2
new file mode 100644 (file)
index 0000000..c4caa0e
--- /dev/null
@@ -0,0 +1,58 @@
+[% 
+    # Org Unit Selector Widget : 
+    #   PROCESS build_org_selector id='selector-id' name='selector-name'
+    BLOCK build_org_selector;
+        first_run = 0;
+        IF !org_unit;
+            org_unit = ctx.aou_tree;
+            first_run = 1;
+%]
+    <select id='[% id %]' name='[% name %]'>
+    [% END %]
+        <option value='[% org_unit.id %]' [% IF org_unit.id == value %] selected='selected' [% END %]>
+            [% 
+                pad = org_unit.ou_type.depth * 2;
+                FOR idx IN [0..pad]; '&nbsp;'; END;
+                org_unit.name;
+            %]
+        </option>
+        [% FOR child IN org_unit.children; PROCESS build_org_selector org_unit = child; END %]
+    [% IF first_run %]
+    </select>
+    [% END %]
+[% END %]
+
+[% PROCESS 'default/opac/marc_attrs.tt2' %]
+[%  USE date;
+    USE money = format('$%.2f');
+    icon_by_mattype = {     # XXX KCLS-specific
+        "a" => "media_book.jpg",
+        "b" => "media_magazines.jpg",
+        "c" => "media_printedmusic.jpg",
+        "d" => "media_microform.jpg",
+        "e" => "media_equipment.jpg",
+        "f" => "media_films.jpg",
+        "g" => "",
+        "h" => "media_dvd.jpg",
+        "i" => "media_bookoncassette.jpg",
+        "j" => "media_musiccd.jpg",
+        "k" => "media_musiccassette.jpg",
+        "l" => "media_musicrecord.jpg",
+        "m" => "media_software.jpg",
+        "n" => "media_bookoncd.jpg",
+        "o" => "media_kit.jpg",
+        "p" => "media_newspaper.jpg",
+        "q" => "media_largeprint.jpg",
+        "r" => "media_3dobject.jpg",
+        "s" => "media_slide.jpg",
+        "t" => "media_online.jpg",
+        "u" => "media_eaudio.jpg",
+        "v" => "media_ebooktext.jpg",
+        "w" => "media_eaudio.jpg",
+        "x" => "media_downloadmusic.jpg",
+        "y" => "media_downloadvideo.jpg",
+        "z" => "media_map.jpg",
+        "2" => "media_cassettewithbook.jpg",
+        "5" => "media_cdwithbook.jpg"
+    };
+%]
diff --git a/Open-ILS/web/templates/default/opac-poc/home.tt2 b/Open-ILS/web/templates/default/opac-poc/home.tt2
new file mode 100644 (file)
index 0000000..03b2ad1
--- /dev/null
@@ -0,0 +1,24 @@
+[% ctx.page_title = "Home" %]
+
+[% BLOCK html_head %]
+<style>
+    #home_div { text-align: center; width: 100%; margin-top: 30px;}
+</style>
+[% END %]
+
+[% WRAPPER "default/opac/base.tt2" %]
+[% PROCESS "default/opac/common.tt2" %]
+
+<div id='home_div'>
+    <img src='/images/eg_logo.jpg'/>
+    <br/><br/>
+    <form action='./results' method='GET'>
+        <input type='text' name='query' size='50' value='[% query %]'/>
+        [% PROCESS build_org_selector name='loc' %]
+        <input type='submit' value='[% l('Go!') %]'/>
+        <input type='hidden' name='page' value='0'/>
+    </form>
+</div>
+
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/login.tt2 b/Open-ILS/web/templates/default/opac-poc/login.tt2
new file mode 100644 (file)
index 0000000..1bae958
--- /dev/null
@@ -0,0 +1,32 @@
+[% BLOCK html_head %]
+<style>
+</style>
+[% END %]
+
+[% 
+    USE CGI;
+    WRAPPER "default/opac/base.tt2"; 
+    ctx.page_title = "Login";
+%]
+
+<div style='width:400px; text-align:center; border: 1px solid #888'>
+    <form method='POST'>
+        <table>
+            <tr>
+                <td>Username or Barcode</td>
+                <td><input name='username' type='text'/></td>
+            </tr>
+            <tr>
+                <td>Password</td>
+                <td><input name='password' type='password'/></td>
+            </tr>
+            <tr>
+                <td colspan='2' style='text-align:center'>
+                    <input type='submit'/>
+                </td>
+            </tr>
+        </table>
+        <input type='hidden' name='redirect_to' value='[% CGI.param('redirect_to') || ctx.referer | replace('^http:', 'https:') %]'/>
+    </form>
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/marc_attrs.tt2 b/Open-ILS/web/templates/default/opac-poc/marc_attrs.tt2
new file mode 100644 (file)
index 0000000..73f12c3
--- /dev/null
@@ -0,0 +1,18 @@
+[% 
+    # Extract MARC fields from XML
+    #   get_marc_attrs( { marc_xml => doc } )
+    BLOCK get_marc_attrs;
+        xml = args.marc_xml;
+        args.isbn = xml.findnodes('//*[@tag="020"]/*[@code="a"]').textContent;
+        args.upc = xml.findnodes('//*[@tag="024"]/*[@code="a"]').textContent;
+        args.issn = xml.findnodes('//*[@tag="022"]/*[@code="a"]').textContent;
+        args.title = xml.findnodes('//*[@tag="245"]/*[@code="a"]').textContent;
+        args.author = xml.findnodes('//*[@tag="100"]/*[@code="a"]').textContent;
+        args.publisher = xml.findnodes('//*[@tag="260"]/*[@code="b"]').textContent;
+        args.pubdate = xml.findnodes('//*[@tag="260"]/*[@code="c"]').textContent;
+        args.mattype = xml.findnodes('//*[@tag="998"]/*[@code="d"]').textContent; # XXX this is KCLS-specific and will need to change
+
+        # clean up the ISBN
+        args.isbn_clean = args.isbn.replace('\ .*', '');
+    END;
+%]
diff --git a/Open-ILS/web/templates/default/opac-poc/myopac/_links.tt2 b/Open-ILS/web/templates/default/opac-poc/myopac/_links.tt2
new file mode 100644 (file)
index 0000000..b034198
--- /dev/null
@@ -0,0 +1,20 @@
+<div>[%
+pages = [
+    {url => "main", name => "My Account"},
+    {url => "circs", name => "Items Out"},
+    {url => "holds", name => "Items on Hold"},
+    {url => "fines", name => "Fines"},
+    {url => "prefs", name => "Account Preferences"},
+    {url => "bookbags", name => "My Bookbags"}
+];
+FOREACH page IN pages %]
+    <span style="margin: 0 0.5em;">
+    [% IF page.url != myopac_page %]<a href="[% page.url %]">[% END;
+        page.name;
+        IF page.url != myopac_page %]</a>
+    [% ELSE; ctx.page_title = page.name; END %]</span>
+[% END %]</div>
+<ul>
+    <li><a href="../home">Home</a></li>
+    <li><a href="../logout">Logout</a></li>
+</ul>
diff --git a/Open-ILS/web/templates/default/opac-poc/myopac/bookbags.tt2 b/Open-ILS/web/templates/default/opac-poc/myopac/bookbags.tt2
new file mode 100644 (file)
index 0000000..0ac2dc0
--- /dev/null
@@ -0,0 +1,52 @@
+[% BLOCK html_head %]
+<style>
+    table { width: 100%; text-align: center; padding: 20px; margin-top: 30px; }
+    table { border-collapse: collapse; }
+    table { padding: 3px; border-bottom: 1px solid #ddd; text-align: left;}
+    table tr:nth-child(odd) { background-color:#ded; }
+    #action_div { width: 95%; }
+    #action-buttons { float:right; }
+</style>
+[% END %]
+
+[% WRAPPER "default/opac/base.tt2" %]
+[% INCLUDE "default/opac/myopac/_links.tt2" myopac_page = "bookbags" %]
+
+[% IF ctx.bookbags.size == 0 %]
+<b>No Bookbags</b>
+[% STOP; END %]
+
+<form method='POST' id='bbag-form'>
+    <div id='action_div'>
+        <div id='action-buttons'>
+            <select name='action'>
+                <option value='delete'>Delete Selected</option>
+                <option value='delete_all'>Delete All</option>
+            </select>
+            <input type='submit' value='Go'/>
+        </div>
+    </div>
+    <table>
+        <thead>
+            <tr>
+                <th>Name</th>
+                <th>Public</th>
+                <th>Created On</th>
+                <th>Items</th>
+            </tr>
+        </thead>
+        <tbody>
+            [% FOR bbag IN ctx.bookbags %]
+                <tr [% IF loop.count % 2 == 1 %] class='bbag-table-odd' [% END %]>
+                    <td>[% bbag.name %]</td>
+                    <td>[% bbag.pub == 't' ? 'Yes' : 'No' %]</td>
+                    <td>[% date.format(ctx.parse_datetime(bbag.create_time),'%Y-%m-%d') %]</td>
+                    <td>XXX</td>
+                </tr>
+            [% END %]
+        </tbody>
+    </table>
+</form>
+
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/myopac/circs.tt2 b/Open-ILS/web/templates/default/opac-poc/myopac/circs.tt2
new file mode 100644 (file)
index 0000000..5f08d2e
--- /dev/null
@@ -0,0 +1,77 @@
+[% BLOCK html_head %]
+<style>
+    table { width: 100%; text-align: center; padding: 20px; margin-top: 30px; }
+    table { border-collapse: collapse; }
+    table { padding: 3px; border-bottom: 1px solid #ddd; text-align: left;}
+    #action_div { width: 95%; }
+    .renew-summary { float:left; padding-right: 10px;}
+    #action-buttons { float:right; }
+    .circ-table-odd { background-color:#ded; }
+    .failure-text { font-weight: bold; color: red; }
+    #circ-form { margin-top: 20px; }
+</style>
+[% END %]
+
+[% PROCESS "default/opac/common.tt2" %]
+[% WRAPPER "default/opac/base.tt2" %]
+[% INCLUDE "default/opac/myopac/_links.tt2" myopac_page = "circs" %]
+
+[% IF ctx.circs.size == 0 %]
+<b>No Items Checked Out</b>
+[% STOP; END %]
+
+<form method='POST' id='circ-form'>
+    <div id='action_div'>
+        [% IF ctx.success_renewals > 0 %]
+            <div class='renew-summary'><b>Successfully renewed [% ctx.success_renewals %] items.</b></div>
+        [% END %]
+        [% IF ctx.failed_renewals > 0 %]
+            <div class='renew-summary'><b>Failed to renew [% ctx.failed_renewals %] items.</b></div>
+        [% END %]
+        <div id='action-buttons'>
+            <button type='submit' value='renew' name='action'>Renew Selected</button>
+            <button type='submit' value='renew_all' name='action'>Renew All</button>
+        </div>
+    </div>
+    <table>
+        <thead>
+            <tr>
+                <th>Title</th>
+                <th>Author</th>
+                <th>Due Date</th>
+                <th>Renewals Remaining</th>
+                <th>Select</th>
+            </tr>
+        </thead>
+        <tbody>
+            [% FOR circ IN ctx.circs %]
+                [% attrs = {marc_xml => circ.marc_xml}; %]
+                [% PROCESS get_marc_attrs args=attrs; %]
+
+                <tr [% IF loop.count % 2 == 1 %] class='circ-table-odd' [% END %]>
+                    <td><a href='../record/[% circ.circ.target_copy.call_number.record.id %]'>[% attrs.title %]</a></td>
+                    <td><a href='../results?query=au:[% attrs.author | url %]'>[% attrs.author %]</a></td>
+                    <td>[% date.format(ctx.parse_datetime(circ.circ.due_date),'%Y-%m-%d') %]</td>
+                    <td><em>[% circ.circ.renewal_remaining %]</em></td>
+                    <td><input name='circ' value='[% circ.circ.id %]' type='checkbox' 
+                        [% IF circ.circ.renewal_remaining < 1 %] disabled='disabled' [% END %]/></td>
+                </tr>
+
+                [% IF circ.renewal_response and circ.renewal_response.textcode != 'SUCCESS' %]
+                <tr [% IF loop.count % 2 == 1 %] class='circ-table-odd' [% END %]>
+                    <td colspan='0'>
+                        <div class='failure-text'>
+                            [% circ.renewal_response.textcode %] 
+                            [% IF circ.renewal_response.payload.fail_part and circ.renewal_response.payload.fail_part != circ.renewal_response.textcode %]
+                                [% circ.renewal_response.payload.fail_part %]
+                            [% END %]
+                        </div>
+                    </td>
+                </tr>
+                [% END %]
+            [% END %]
+        </tbody>
+    </table>
+</form>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/myopac/fines.tt2 b/Open-ILS/web/templates/default/opac-poc/myopac/fines.tt2
new file mode 100644 (file)
index 0000000..727322f
--- /dev/null
@@ -0,0 +1,107 @@
+[% BLOCK html_head %]
+<style>
+    table { width: 100%; text-align: center; padding: 20px; margin-top: 30px; }
+    table { border-collapse: collapse; }
+    table { padding: 3px; border-bottom: 1px solid #ddd; text-align: left;}
+    table tr:nth-child(odd) { background-color:#ded; }
+    h2 { margin-bottom: 0; }
+</style>
+[% END %]
+
+[% PROCESS "default/opac/common.tt2" %]
+[% WRAPPER "default/opac/base.tt2" %]
+[% INCLUDE "default/opac/myopac/_links.tt2" myopac_page = "fines" %]
+<h2>Summary</h2>
+<table>
+    <thead>
+        <tr>
+            <th>Total Owed</th>
+            <th>Total Paid</th>
+            <th>Balance Owed</th>
+        </tr>
+    </thead>
+    <tbody>
+        <tr>
+            <td>[% money(ctx.fines.total_owed) %]</td>
+            <td>[% money(ctx.fines.total_paid) %]</td>
+            <td>[% money(ctx.fines.balance_owed) %]</td>
+        </tr>
+    </tbody>
+</table>
+
+[% IF ctx.fines.circulation.size > 0 %]
+<h2>Overdue materials</h2>
+<table>
+    <thead>
+        <tr>
+            <th>Title</th>
+            <th>Author</th>
+            <th>Checkout Date</th>
+            <th>Due Date</th>
+            <th>Date Returned</th>
+            <th>Balance Owed</th>
+        </tr>
+    </thead>
+    <tbody>
+    [% FOR f IN ctx.fines.circulation %]
+        [% attrs = {marc_xml => f.marc_xml}; %]
+        [% PROCESS get_marc_attrs args=attrs; %]
+        <tr>
+            <td>[% attrs.title %]</td>
+            <td>[% attrs.author %]</td>
+            <td>[% date.format(
+                ctx.parse_datetime(f.xact.circulation.xact_start), "%Y-%m-%d"
+            ) %]</td>
+            <td>[% date.format(
+                ctx.parse_datetime(f.xact.circulation.due_date), "%Y-%m-%d"
+            ) %]</td>
+            <td>[%
+                IF f.xact.circulation.checkin_time;
+                    date.format(
+                        ctx.parse_datetime(f.xact.circulation.checkin_time),
+                        "%Y-%m-%d"
+                    );
+                END %]</td><!-- XXX TODO display stop_fines_time if set? Display something instead of blank like "fines accruing" ? -->
+            <td>[% money(f.xact.balance_owed) %]</td>
+        </tr>
+    [% END %]
+    </tbody>
+</table>
+[% END %]
+
+[% IF ctx.fines.grocery.size > 0 %]
+<h2>Other Fees</h2>
+<table>
+    <thead>
+        <tr>
+            <th>Transaction Start Time</th>
+            <th>Last Payment Time</th>
+            <th>Initial Amount Owed</th>
+            <th>Total Amount Paid</th>
+            <th>Balance Owed</th>
+            <th>Billing Type</th>
+        </tr>
+    </thead>
+    <tbody>
+    [% FOR f IN ctx.fines.grocery %]
+        <tr>
+            <td>[%
+                date.format(
+                    ctx.parse_datetime(f.xact.xact_start), "%Y-%m-%d"
+                ) %]</td>
+            <td>[% IF f.xact.last_payment_ts;
+                    date.format(
+                        ctx.parse_datetime(f.xact.last_payment_ts), "%Y-%m-%d"
+                        );
+                    END %]</td>
+            <td>[% money(f.xact.total_owed) %]</td>
+            <td>[% money(f.xact.total_paid) %]</td>
+            <td>[% money(f.xact.balance_owed) %]</td>
+            <td>[% f.xact.last_billing_type %]</td>
+        </tr>
+    [% END %]
+    </tbody>
+</table>
+[% END %]
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/myopac/holds.tt2 b/Open-ILS/web/templates/default/opac-poc/myopac/holds.tt2
new file mode 100644 (file)
index 0000000..ce09725
--- /dev/null
@@ -0,0 +1,94 @@
+[% BLOCK html_head %]
+<style>
+    table { width: 100%; text-align: center; padding: 20px; margin-top: 30px; }
+    table { border-collapse: collapse; }
+    table { padding: 3px; border-bottom: 1px solid #ddd; text-align: left;}
+    table tr:nth-child(odd) { background-color:#ded; }
+    #action_div { width: 95%; }
+    #action-buttons { float:right; }
+</style>
+[% END %]
+
+[%  PROCESS "default/opac/common.tt2";
+    WRAPPER "default/opac/base.tt2";
+    INCLUDE "default/opac/myopac/_links.tt2" myopac_page = "holds" %]
+
+[% IF ctx.holds.size == 0 %]
+<b>No Items On Hold</b>
+[% STOP; END %]
+
+<form method='POST'>
+
+    <div id='action_div'>
+        <div id='action-buttons'>
+            <select name='action'>
+                <option value='cancel'>Cancel Selected</option>
+                <option value='cancel_all'>Cancel All</option>
+                <option value='suspend'>Suspend Selected</option>
+                <option value='suspend_all'>Suspend All</option>
+                <option value='activate'>Activate Selected</option>
+                <option value='activate_all'>Activate All</option>
+            </select>
+            <input type='Submit' value='Go'/>
+        </div>
+    </div>
+    <table>
+        <thead>
+            <tr>
+                <th>Title</th>
+                <th>Author</th>
+                <th>Formats</th>
+                <th>Pickup Location</th>
+                <th>Status</th>
+                <th>Active</th>
+                <th>Activate on...</th>
+                <th>Expiration Date</th>
+                <th>Select</th>
+            </tr>
+        </thead>
+        <tbody>
+            [% FOR hold IN ctx.holds %]
+                [% attrs = {marc_xml => hold.marc_xml}; %]
+                [% PROCESS get_marc_attrs args=attrs; %]
+            <tr>
+                <td><a href='../record/[% hold.hold.bre.id %]'>[% attrs.title %]</a></td>
+                <td><a href='../results?query=au:[% attrs.author | url %]'>[% attrs.author %]</a></td>
+                <td>
+                    [%
+                        key = attrs.mattype;
+                        format_desc = ctx.find_citm(key).value;
+                        icon_filename = icon_by_mattype.$key;
+                        IF icon_filename;
+                    %]<!-- XXX in situations where we might show M-type holds, this won't be good enough -->
+                    <img alt="[% format_desc %]" title="[% format_desc %]"
+                        src="/images/mattype/[% icon_filename %]" />
+                    [%  END %]
+                </td>
+                <td>[% ctx.find_aou(hold.hold.hold.pickup_lib).name %]</td>
+                <td>[%
+                    IF hold.hold.status == 4;
+                        "Available";
+                    ELSIF hold.hold.estimated_wait;
+                        "Estimated wait (days): "; hold.hold.estimated_wait;
+                    ELSIF hold.hold.status == 3;
+                        "In Transit";
+                    ELSIF hold.hold.status < 3;
+                        "Waiting for copy";
+                    END;
+                %]</td>
+                <td>[% IF hold.hold.hold.frozen == 't' %] No [% ELSE %] Yes [% END %]</td>
+                <td>[% 
+                    IF hold.hold.hold.frozen == 't' AND hold.hold.hold.thaw_date;
+                        date.format(ctx.parse_datetime(hold.hold.hold.thaw_date),'%Y-%m-%d'); 
+                    ELSE;
+                        '-';
+                    END 
+                %]</td>
+                <td>[% hold.hold.hold.expire_time ? hold.hold.hold.expire_time : '-' %]</td>
+                <td><input type='checkbox' name='hold_id' value='[% hold.hold.hold.id %]'/></td>
+            </tr>
+            [% END %]
+        </tbody>
+    </table>
+</form> 
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/myopac/main.tt2 b/Open-ILS/web/templates/default/opac-poc/myopac/main.tt2
new file mode 100644 (file)
index 0000000..33a533e
--- /dev/null
@@ -0,0 +1,39 @@
+[% BLOCK html_head %]
+<style>
+    table { text-align: center; padding: 20px; margin-top: 30px; border-collapse: collapse; }
+    table td { padding: 5px 15px 5px 15px; border-bottom: 1px solid #ddd; text-align: left;}
+    table tr:nth-child(odd) { background-color:#ded; }
+</style>
+[% END %]
+
+[% WRAPPER "default/opac/base.tt2" %]
+[% INCLUDE "default/opac/myopac/_links.tt2" myopac_page = "main" %]
+<table>
+    <tr>
+        <td>First Name</td>
+        <td>[% ctx.user.first_given_name %]</td>
+    </tr>
+    <tr>
+        <td>Middle Name</td>
+        <td>[% ctx.user.second_given_name %]</td>
+    </tr>
+    <tr>
+        <td>Last Name</td>
+        <td>[% ctx.user.family_name %]</td>
+    </tr>
+    <tr>
+        <td>Library Card</td>
+        <td>[% ctx.user.card.barcode %]</td>
+    </tr>
+    <tr>
+        <td>Email Address</td>
+        <td>[% ctx.user.email %]</td>
+        <td><a href='update_email'>Change</a></td>
+    </tr>
+    <tr>
+        <td>Phone</td>
+        <td>[% ctx.user.day_phone %]</td>
+    </tr>
+</table>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/myopac/prefs.tt2 b/Open-ILS/web/templates/default/opac-poc/myopac/prefs.tt2
new file mode 100644 (file)
index 0000000..d9a60ba
--- /dev/null
@@ -0,0 +1,15 @@
+[% BLOCK html_head %]
+<style>
+    table { width: 100%; text-align: center; padding: 20px; margin-top: 30px; }
+    table { border-collapse: collapse; }
+    table { padding: 3px; border-bottom: 1px solid #ddd; text-align: left;}
+    table tr:nth-child(odd) { background-color:#ded; }
+</style>
+[% END %]
+
+[% WRAPPER "default/opac/base.tt2" %]
+[% INCLUDE "default/opac/myopac/_links.tt2" myopac_page = "prefs" %]
+<p><em>XXX TODO Need to find out whether the list of pref fields can/should be generated
+    from db entries or something.</em></p>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/myopac/update_email.tt2 b/Open-ILS/web/templates/default/opac-poc/myopac/update_email.tt2
new file mode 100644 (file)
index 0000000..7666c8f
--- /dev/null
@@ -0,0 +1,20 @@
+[% BLOCK html_head %]
+<style>
+    table { text-align: center; padding: 20px; margin-top: 30px; border-collapse: collapse; }
+    table td { padding: 5px 15px 5px 15px; border-bottom: 1px solid #ddd; text-align: left;}
+    table tr:nth-child(odd) { background-color:#ded; }
+</style>
+[% END %]
+
+[% WRAPPER "default/opac/base.tt2" %]
+[% INCLUDE "default/opac/myopac/_links.tt2" %]
+
+<form method='POST'>
+    <table> 
+        <tr><td>Current Email</td><td>[% ctx.user.email %]</td></tr>
+        <tr><td>New Email</td><td><input type='text' name='email'/></td></tr>
+    </table>
+    <input type='submit'/>
+</form>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/place_hold.tt2 b/Open-ILS/web/templates/default/opac-poc/place_hold.tt2
new file mode 100644 (file)
index 0000000..bfbee07
--- /dev/null
@@ -0,0 +1,33 @@
+[% BLOCK html_head %]
+<style>
+</style>
+[% END %]
+
+[% 
+    USE CGI;
+    PROCESS "default/opac/common.tt2";
+    WRAPPER "default/opac/base.tt2"; 
+    ctx.page_title = "Place Hold";
+    attrs = {marc_xml => ctx.marc_xml};
+    PROCESS get_marc_attrs args=attrs;
+%]
+
+
+<div>
+    <div>Placing hold on [% attrs.title %], by [% attrs.author %]</div>
+    [% IF ctx.hold_success %] 
+        <div>Succeeded</div>
+    [% ELSIF ctx.hold_failed %]
+        <div>Failed...</div>
+    [% ELSE %]
+    <form action='place_hold' method='POST'>
+        Choose a pickup Library [% PROCESS build_org_selector name='pickup_lib' value=ctx.default_pickup_lib %]
+        <input type='Submit'/>
+        <input type='hidden' name='hold_target' value='[% CGI.param('hold_target') | html %]'/>
+        <input type='hidden' name='hold_type' value='[% CGI.param('hold_type') | html %]'/>
+        <input type='hidden' name='redirect_to' value='[% ctx.referer | html %]'/>
+    </form>
+    [% END %]
+</div>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/record.tt2 b/Open-ILS/web/templates/default/opac-poc/record.tt2
new file mode 100644 (file)
index 0000000..24f1203
--- /dev/null
@@ -0,0 +1,82 @@
+[% BLOCK html_head %]
+<style>
+    table { width: 100%; padding: 20px; margin-top: 30px; }
+    table { border-collapse: collapse; }
+    table td { padding: 3px; border-bottom: 1px solid #ddd; text-align: left;}
+    table th { padding: 3px; border-bottom: 1px solid #ddd; text-align: left;}
+    table tr:nth-child(even) { background-color:#ded; }
+    #record_table td { padding-left: 15px; padding-right: 15px; }
+</style>
+[% END %]
+
+[% 
+    WRAPPER "default/opac/base.tt2"; 
+    PROCESS "default/opac/common.tt2";
+    ctx.page_title = "Details";
+    record = ctx.record;
+    attrs = {marc_xml => ctx.marc_xml};
+    PROCESS get_marc_attrs args=attrs;
+%]
+
+<div id='detail_div'>
+    <table id='record_table' style='width:auto'>
+        <tr>
+            <td rowspan='10' style='width:55px; vertical-align:top; padding-right:4px;'>
+                [% IF attrs.isbn_clean || attrs.upc %]
+                <img width='50' height='70' src='[% ctx.media_prefix %]/opac/extras/ac/jacket/small/[% attrs.isbn_clean || attrs.upc %]'/>
+                [% END %]
+            </td>
+        </tr>
+        [% IF attrs.title %]<tr><td>Title</td><td>[% attrs.title %]</td></tr>[% END %]
+        [% IF attrs.author %]<tr><td>Author</td><td><a href='../results?query=au:[% attrs.author | uri %]'>[% attrs.author %]</a></td></tr>[% END %]
+        [% IF attrs.isbn %]<tr><td>ISBN</td><td>[% attrs.isbn %]</td></tr>[% END %]
+        [% IF attrs.issn %]<tr><td>ISSN</td><td>[% attrs.issn %]</td></tr>[% END %]
+        [% IF attrs.upc %]<tr><td>UPC</td><td>[% attrs.upc %]</td></tr>[% END %]
+        [% IF attrs.pubdate %]<tr><td>Publication Date</td><td>[% attrs.pubdate %]</td></tr>[% END %]
+        [% IF attrs.publisher %]<tr><td>Publishere</td><td>[% attrs.publisher %]</td></tr>[% END %]
+        <tr>
+            <td>Subjects</td>
+            <td>
+            [% FOR node IN ctx.marc_xml.findnodes('//*[@tag="650"]') %]
+                [% 
+                    s0 = node.childNodes.0.textContent;
+                    s1 = node.childNodes.1.textContent;
+                %]
+                [% IF s0 %]
+                    <a href='../results?query=su:[% s0 | url %]'>[% s0 %]</a>
+                    [% IF s1 %]
+                    <span>--</span>
+                    <a href='../results?query=su:[% s1 | url %]'>[% s1 %]</a>
+                    [% END %]
+                    <br/>
+                [% END %]
+            [% END %]
+            </td>
+        </tr>
+    </table>
+    <table id='copy_table'>
+        <thead>
+            <tr>
+                <th>Owning Lib</th>
+                <th>Call Number</th>
+                <th>Barcode</th>
+                <th>Status</th>
+            </tr>
+        </thead>
+        <tbody>
+        [% FOR acn IN record.call_numbers %]
+            [% FOR acp IN acn.copies %]
+                <tr>
+                    <td>[% ctx.find_aou(acn.owning_lib).shortname %]</td>
+                    <td>[% acn.label %]</td>
+                    <td>[% acp.barcode %]</td>
+                    <td>[% ctx.find_ccs(acp.status).name %]</td>
+                </tr>
+            [% END %]
+        [% END %]
+        </tbody>
+    </table>
+</div>
+
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac-poc/results.tt2 b/Open-ILS/web/templates/default/opac-poc/results.tt2
new file mode 100644 (file)
index 0000000..9ecead4
--- /dev/null
@@ -0,0 +1,117 @@
+[% BLOCK html_head %]
+<style>
+    #body_table { width: 100%; margin-top: 20px; }
+    #left_block { width: 15%; vertical-align: top; }
+    #right_block { width: auto; vertical-align: top;}
+    #record_table { border-collapse: collapse; width:100%; }
+    #record_table td { padding: 3px; border-bottom: 1px solid #ddd; }
+    #record_table tr:nth-child(odd) { background-color:#ded; }
+    .record-table-odd { background-color:#ded; }
+    #form_div { text-align: center; width: 100%; margin-top: 10px;}
+    #links_div { margin-bottom: 10px; padding: 5px;}
+</style>
+[% END %]
+
+[% 
+    USE CGI;
+    USE POSIX;
+    WRAPPER "default/opac/base.tt2"; 
+    PROCESS "default/opac/common.tt2";
+    ctx.page_title = "Results";
+    page = CGI.param('page') || 0; 
+    query = CGI.param('query');
+    page_count = POSIX.ceil(ctx.hit_count / ctx.page_size);
+    loc = CGI.param('loc');
+%]
+
+<div id='form_div'>
+    <form action='./results' method='GET'>
+        <input type='text' name='query' size='50' value='[% query %]'/>
+        [% PROCESS build_org_selector name='loc' value=loc %]
+        <input type='submit'/>
+        <input type='hidden' name='page' value='0'/>
+    </form>
+</div>
+
+<table id='body_table'>
+    <tr>
+        <td id='left_block'>
+                [% IF ctx.user; %]
+                    <div id='links_div'>
+                        <div><a href='home'>Home</a></div>
+                        <div><a href='myopac/main'>Account</a></div>
+                        <div><a href='logout'>Logout</a></div>
+                    </div>
+                    <hr/>
+                    <table>
+                        <tr><td colspan='2' style='border-bottom:1px solid #9A9'>Signed in as [% ctx.user.usrname %]</td></tr>
+                        <tr><td>Total Holds</td><td>[% ctx.user_stats.holds.total %]</td></tr>
+                        <tr><td>Ready Holds</td><td>[% ctx.user_stats.holds.ready %]</td></tr>
+                        <tr><td>Items Out</td><td>[% ctx.user_stats.checkouts.out %]</td></tr>
+                        <tr><td>Fines</td><td>$[% ctx.user_stats.fines.balance_owed %]</td></tr>
+                    </table>
+                [% ELSE %]
+                    [% 
+                        login = CGI.url("-path" => 1).replace('^http:', 'https:').replace('/results','/login');
+                    %]
+                    <a href='[% login %]'>Login</a>
+                [% END %]
+            </div>
+            <div>
+                [% FOR facet_type IN ctx.search_facets.keys %]
+                    [% cmf = ctx.search_facets.$facet_type.cmf %]
+                    <b>[% cmf.label %]</b>
+                    <ul>
+                        [% FOR facet IN ctx.search_facets.$facet_type.data.keys %]
+                            [% facet_count = ctx.search_facets.$facet_type.data.$facet %]
+                            <li><a href='results?query=[% query | url %]&facet=[% cmf.field_class %]|[% cmf.name %][[% facet | url %]]'>[% facet_count %] / [% facet %]</a></li>
+                        [% END %]
+                    </ul>
+                [% END %]
+            </div>
+        </td>
+        <td id='right_block'>
+            <div>
+                <span>[% l('Hits: [_1] / Page [_2] of [_3]', ctx.hit_count, page + 1, page_count) %]</span>
+                [% 
+                    q = query | url;
+                    np_link = '?query=' _ q;
+                    IF loc; np_link = np_link _ "&loc=" _ loc; END;
+                    IF depth or depth == 0; np_link = np_link _ "&depth=" _ depth; END;
+                %]
+                <a [% IF page > 0 %] href='[% np_link %]&page=[% page - 1 %]' [% END %]>Prev</a>  
+                <a [% IF (page + 1) < page_count %] href='[% np_link %]&page=[% page + 1 %]' [% END %]>Next</a>
+            </div>
+            <table id='record_table'>
+                [%
+                FOR rec IN ctx.records;
+                    attrs = {marc_xml => rec.marc_xml};
+                    PROCESS get_marc_attrs args=attrs;
+                %]
+                <tr [% IF loop.count % 2 == 1 %] class='record-table-odd' [% END %]>
+                    <td style='width:52px;height:72px'>
+                        [% IF attrs.isbn %]
+                        <img width='50' height='70' src='[% ctx.media_prefix %]/opac/extras/ac/jacket/small/[% attrs.isbn_clean || attrs.upc %]'/>
+                        [% END %]
+                    </td>
+                    <td width='auto'>
+                        <div width='99%'>
+                            <div style='float:left'>
+                                <a href='record/[% rec.bre.id %]'>[% attrs.title %]</a>
+                            </div>
+                            <div style='float:right'>
+                                <span>[% rec.copy_counts.available %] / [% rec.copy_counts.visible %]</span>
+                                <span style='padding-left:10px;'><a href='place_hold?hold_target=[% rec.bre.id %]&hold_type=T'>Hold</a></span>
+                            </div>
+                        </div><br/>
+                        <div>[% attrs.author %]</div>
+                        <div>[% attrs.isbn || attrs.issn || attrs.upc %] [% attrs.publisher %] [% attrs.pubdate %]</div>
+                    </td>
+                </tr>
+                [% END %]
+            </table>
+        </td>
+    </tr>
+
+</table>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/advanced.tt2 b/Open-ILS/web/templates/default/opac/advanced.tt2
new file mode 100644 (file)
index 0000000..5c953a3
--- /dev/null
@@ -0,0 +1,23 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/base.tt2";
+    INCLUDE "default/opac/parts/topnav.tt2";
+    ctx.page_title = l("Advanced Search") %]
+    <div id="search-wrapper">
+        [% INCLUDE "default/opac/parts/printnav.tt2" %]
+        <div id="adv_search_parent">
+            <div id="adv_search_tabs">
+                <a href="#" alt="[% l('Advanced Search') %]" id="adv_search"></a>
+<!--                <a href="#" alt="[% l('Numeric Search') %]" id="num_search"></a>
+                    <a href="#" alt="[% l('Expert Search') %]" id="expert_search"></a> -->
+            </div>
+        </div>
+    </div>
+    <div id="content-wrapper">
+        <div id="main-content">
+            <div class="advanced_div">
+            [% INCLUDE "default/opac/parts/advanced/search.tt2" %]
+            </div>
+            <div class="common-full-pad"></div>        
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/home.tt2 b/Open-ILS/web/templates/default/opac/home.tt2
new file mode 100644 (file)
index 0000000..5e1fe41
--- /dev/null
@@ -0,0 +1,16 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/base.tt2";
+    INCLUDE "default/opac/parts/topnav.tt2";
+    ctx.page_title = l("Home") %]
+    <div id="search-wrapper">
+        [% INCLUDE "default/opac/parts/printnav.tt2" %]
+        [% INCLUDE "default/opac/parts/searchbar.tt2" %]
+    </div>
+    <div id="content-wrapper">
+        <div id="main-content-home">
+            <div class="common-full-pad"></div>
+            [% INCLUDE "default/opac/parts/homesearch.tt2" %]
+            <div class="common-full-pad"></div>        
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/login.tt2 b/Open-ILS/web/templates/default/opac/login.tt2
new file mode 100644 (file)
index 0000000..5f4d03f
--- /dev/null
@@ -0,0 +1,27 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/base.tt2";
+    INCLUDE "default/opac/parts/topnav.tt2";
+    ctx.page_title = l("Account Login") %]
+    <div id="search-wrapper">
+        [% INCLUDE "default/opac/parts/printnav.tt2" %]
+        [% INCLUDE "default/opac/parts/searchbar.tt2" %]
+    </div>
+    <div id="content-wrapper">
+        <div id="main-content">
+            [% INCLUDE "default/opac/parts/login/form.tt2" %]
+            <div class="clear-both very-big-height"></div>     
+            <script type="text/javascript">
+                /* Note: when common browsers suppor HTML5 "autofocus", we can remove this */
+                var _onload = window.onload;
+                window.onload = function() {
+                    try {
+                        document.getElementById("username_field").focus();
+                        if (_onload) _onload();
+                    } catch (E) {
+                        void(0);
+                    }
+                };
+            </script>
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/mylist.tt2 b/Open-ILS/web/templates/default/opac/mylist.tt2
new file mode 100644 (file)
index 0000000..2ec8a5d
--- /dev/null
@@ -0,0 +1,20 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/base.tt2";
+    INCLUDE "default/opac/parts/topnav.tt2";
+    ctx.page_title = l("Record Detail") %]
+    <div id="search-wrapper">
+        [% INCLUDE "default/opac/parts/printnav.tt2" %]
+        [% INCLUDE "default/opac/parts/searchbar.tt2" %]
+    </div>
+    <div id="content-wrapper">
+        <div id="main-content">
+            [%  IF ctx.mylist.size;
+                    INCLUDE "default/opac/parts/anon_list.tt2";
+                ELSE %]
+                <div class="opac-auto-171 opac-auto-097">[% l("You have not created a list yet."); %]</div>
+                [% END %]
+            <div class="common-full-pad"></div>        
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/circ_history.tt2 b/Open-ILS/web/templates/default/opac/myopac/circ_history.tt2
new file mode 100644 (file)
index 0000000..8848693
--- /dev/null
@@ -0,0 +1,102 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/marc_misc.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+    myopac_page = "circs"
+    limit = ctx.circ_history_limit;
+    offset = ctx.circ_history_offset;
+%]
+
+<div style="padding:0px;">
+    
+    <div id="acct_checked_tabs" style="padding-bottom: 12px;color:#666;">
+        <div class="align selected">
+            <a href='circs'><img src="[% ctx.media_prefix %]/images/sub_checked_out_off.jpg"/></a>
+        </div>
+        <div class="align">
+            <img src="[% ctx.media_prefix %]/images/sub_checked_hist_on.jpg"/>
+        </div>
+        <div class="clear-both"></div>
+    </div>
+
+    <div class="header_middle">
+        <span class="float-left">[% l('Previously Checked Out Items') %]</span>
+        <span class='float-left' style='padding-left: 10px;'>
+            <a href='circ_history?limit=[% limit %]&amp;offset=[% offset - limit %]'
+                [% IF offset == 0 %] class='invisible' [% END %]><span class="nav_arrow_fix">&#9668;</span>[% l('Previous') %]</a>
+            [%# TODO: get total to prevent paging off then end of the list.. %]
+            <a href='circ_history?limit=[% limit %]&amp;offset=[% offset + limit %]'
+               [% IF ctx.circs.size < limit %] class='invisible' [% END %] >[% l('Next') %]<span class="nav_arrow_fix">&#9658;</span></a>
+        </span>
+        <span class="float-right">
+            <a class="hide_me" href="#">[% l('Export List') %]</a>
+        </span>
+    </div>
+    <div class="clear-both"></div>
+
+    [% IF ctx.circs.size < 1 %]
+    <div class="opac-auto-079">
+        <big><strong>[% l('There are no items in your circulation history.') %]</strong></big>
+    </div>
+    [% ELSE %]
+
+    <div id='checked_main'>
+        <table style='border-collapse:collapse;'>
+            <thead id="acct_checked_main_header">
+                <tr>
+                    <td width="32%" style="padding-left:5px;">
+                        <span title="Click to sort" class='pointer'>[% l('Title') %]</span> /
+                        <span title="Click to sort" class='pointer'>[% l('Author') %]</span>
+                    </td>
+                    <td width="10%" style="padding-left:5px;">
+                        <span title="Click to sort" class='pointer'>[% l('Checkout Date') %]</span>
+                    </td>
+                    <td width="10%" style="padding-left:5px;">
+                        <span title="Click to sort" class='pointer'>[% l('Due Date') %]</span>
+                    </td>
+                    <td width="10%" style="padding-left:5px;">
+                        <span title="Click to sort" class='pointer'>[% l('Date Returned') %]</span>
+                    </td>
+                    <td width="16%">
+                        <span title="Click to sort" class='pointer'>[% l('Barcode') %]</span>
+                    </td>
+                    <td width="22%">
+                        <span title="Click to sort" class='pointer'>[% l('Call Number') %]</span>
+                    </td>
+                </tr>
+            </thead>
+            <tbody>
+                [% FOR circ IN ctx.circs;
+                    attrs = {marc_xml => circ.marc_xml};
+                    PROCESS get_marc_attrs args=attrs; %]
+                    <tr>
+                        <td style="padding-left:5px;padding-bottom:10px;">
+                            <a href="[% ctx.opac_root %]/record/[% circ.circ.target_copy.call_number.record.id %]" 
+                                name="[% l('Catalog record') %]">[% attrs.title %]</a>
+                            [% IF attrs.author %] /
+                            <a href="[% ctx.opac_root %]/results?qtype=author&amp;query=[% attrs.author | replace('[,\.:;]', '') | url %]">[% attrs.author %]</a>
+                            [% END %]
+                        </td>
+                        <td style="padding-left:5px;">
+                            [% date.format(ctx.parse_datetime(circ.circ.xact_start),DATE_FORMAT); %]
+                        </td>
+                        <td style="padding-left:5px;">
+                            [% date.format(ctx.parse_datetime(circ.circ.due_date),DATE_FORMAT); %]
+                        </td>
+                        <td style="padding-left:5px;">
+                            [% 
+                                IF circ.circ.checkin_time; 
+                                    date.format(ctx.parse_datetime(circ.circ.checkin_time),DATE_FORMAT); 
+                                ELSE; %]
+                                <span style='color:blue;'>*</span><!-- meh -->
+                            [% END; %]
+                        </td>
+                        <td>[% circ.circ.target_copy.barcode %]</td>
+                        <td>[% circ.circ.target_copy.call_number.label %]</td>
+                    </tr>
+                [% END %]
+            </tbody>
+        </table>
+    </div>
+    [% END %]
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/circs.tt2 b/Open-ILS/web/templates/default/opac/myopac/circs.tt2
new file mode 100644 (file)
index 0000000..67f94b8
--- /dev/null
@@ -0,0 +1,166 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+    myopac_page = "circs"  %]
+<div id='myopac_checked_div' style="padding:0px;">
+
+    <div id="acct_checked_tabs" style="padding-bottom: 12px;color:#666;">
+        <div class="align selected">
+            <img src="[% ctx.media_prefix %]/images/sub_checked_out_on.jpg" />
+        </div>
+        <div class="align">
+            <a href="circ_history"><img
+                src="[% ctx.media_prefix %]/images/sub_checked_hist_off.jpg" /></a>
+        </div>
+        <div class="clear-both"></div>
+    </div>
+
+    <div class="header_middle">
+        <span class="float-left">[% l('Current Items Checked Out') %]</span>
+        <span class="float-right">
+            <a class="hide_me" href="#">[% l('Export List') %]</a>
+        </span>
+    </div>
+    <div class="clear-both"></div>
+    [% IF ctx.circs.size < 1 %]
+    <div class="opac-auto-079">
+        <big><strong>[% l('You have no items checked out.') %]</strong></big>
+    </div>
+    [% ELSE %]
+    [% IF ctx.success_renewals %]
+    <div class="renew-summary">
+        [% l("Successfully renewed [_1] item(s)", ctx.success_renewals) %]
+    </div>
+    [% END %]
+    [% IF ctx.failed_renewals %]
+    <div class="renew-summary red">
+        [% l("Failed to renew [_1] item(s)", ctx.failed_renewals) %]
+    </div>
+    [% END %]
+    <div id='checked_main'>
+        <form method="POST" id="circ-form"
+            onsubmit="return confirm('[% l("Are you sure you wish to renew the selected item(s)?") %]');">
+        <table cellpadding='0' cellspacing='0' class="opac-auto-097b">
+            <tr>
+                <td>
+                    <select name="action">
+                        <option value="renew">[% l('Renew Selected Titles') %]</option>
+                    </select>
+                </td>
+                <td style="padding-left:9px;">
+                    <input type="image"
+                        alt="[% l('Go') %]" title="[% l('Go') %]"
+                        src="[% ctx.media_prefix %]/images/go-btn.png" /></a>
+                </td>
+                <td style="padding-left:5px;">
+                    <a href="#"><img alt="Renewing Help"
+                        src="[% ctx.media_prefix %]/images/question-mark.png" /></a>
+                </td>
+            </tr>
+        </table>
+        <table id="acct_checked_main_header" cellpadding='0' cellspacing='0'
+            border='0'>
+            <tr>
+                <td width="1%" style="padding-left:10px;">
+                    <input type="checkbox" id="check_all_checked"
+                        onclick="var inputs=document.getElementsByTagName('input'); for (i = 0; i < inputs.length; i++) { if (inputs[i].name == 'circ' && !inputs[i].disabled) inputs[i].checked = this.checked;}"
+                    />
+                </td>
+                <td width="40%" style="padding-left:5px;">
+                    <span title="Click to sort" class='pointer'>
+                        Title
+                    </span> /
+                    <span title="Click to sort" class='pointer'>
+                        Author
+                    </span>
+                </td>
+                <td width="8%" style="padding-right:5px;" align="center">
+                    <span title="Click to sort" class='pointer'>Renews<br />Left
+                    </span>
+                </td>
+                <td width="13%" style="padding-left:5px;">
+                    <span title="Click to sort" class='pointer'>Due Date</span>
+                </td>
+                <td width="16%">
+                    <span title="Click to sort" class='pointer'>barcode</span>
+                </td>
+                <td width="22%">
+                    <span title="Click to sort" class='pointer'>call number</span>
+                </td>
+            </tr>
+        </table>
+   
+        <div id="checked_temp_parent">
+            <div id="acct_checked_temp">
+                <table cellpadding='0' cellspacing='0' border='0'
+                    style="margin-top:5px;">
+                    [% FOR circ IN ctx.circs;
+                        attrs = {marc_xml => circ.marc_xml};
+                        PROCESS get_marc_attrs args=attrs; %]
+                    <tr>
+                        <td width="1%" style="padding-left:10px;" valign="top">
+                            <input type="checkbox" name="circ"
+                                [% IF circ.circ.renewal_remaining < 1; l('disabled="disabled"'); END %]
+                                value="[% circ.circ.id %]" />
+                        </td>
+                        <td width="40%"
+                            style="padding-left:5px;padding-bottom:10px;"
+                            name="author">
+                            <a href="[% ctx.opac_root %]/record/[% circ.circ.target_copy.call_number.record.id %]" name="[% l('Catalog record') %]">[% attrs.title %]</a>
+                            [% IF attrs.author %] /
+                            <a href="[% ctx.opac_root %]/results?qtype=author&amp;query=[% attrs.author | replace('[,\.:;]', '') | url %]">[% attrs.author %]</a>
+                            [% END %]
+                        </td>
+                        <td width="8%" name="renewals" align="center">
+                            [% circ.circ.renewal_remaining %]
+                        </td>
+                        <td width="13%" style="padding-left:5px;"
+                            name="due_date">
+                            [% date.format(ctx.parse_datetime(circ.circ.due_date),DATE_FORMAT) %]
+                        </td>
+                        <td width="16%" name="barcode">
+                            [% circ.circ.target_copy.barcode %]
+                        </td>
+                        <td width="22%" name="call_number">
+                            [% circ.circ.target_copy.call_number.label %]
+                        </td>
+                    </tr>
+                    [%  IF circ.renewal_response AND
+                            circ.renewal_response.textcode != 'SUCCESS' %]
+                    <tr>
+                        <td colspan="6">[%# XXX colspan="0" does not work in IE %]
+                            <span class="failure-text" title="[% circ.renewal_response.textcode %] / [% circ.renewal_response.payload.fail_part %]">
+                                [% circ.renewal_response.desc || circ.renewal_response.payload.fail_part || circ.renewal_response.textcode %]
+                            </span>
+                        </td>
+                    </tr>
+                    [%  END;
+                    END %]
+                </table>
+            </div>
+        </div>
+        </form>
+    </div>
+    [% END %]
+    <div id='non_cat_circs_div' class='hide_me'>
+        <br/>
+        <div style='text-align: center'><b>[% l("Other Circulations") %]</b></div>
+        <table class='data_grid' width='100%'>
+            <thead>
+                <tr>
+                    <td>[% l("Circulating Library") %]</td>
+                    <td>[% l("Circulation Type") %]</td>
+                    <td>[% l("Please return by ...") %]</td>
+                </tr>
+            </thead>
+            <tbody id='non_cat_circs_tbody'>
+                <tr id='non_cat_circs_row'>
+                    <td name='circ_lib'/>
+                    <td name='item_type'/>
+                    <td name='circ_time'/>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/hold_history.tt2 b/Open-ILS/web/templates/default/opac/myopac/hold_history.tt2
new file mode 100644 (file)
index 0000000..048dbb2
--- /dev/null
@@ -0,0 +1,127 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/marc_misc.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+    myopac_page = "holds"  
+    limit = ctx.hold_history_limit;
+    offset = ctx.hold_history_offset;
+%]
+
+<div id='myopac_holds_div'>
+
+    <div id="acct_holds_tabs" style="padding-bottom: 12px;color:#666;">
+        <div class="align selected">
+            <a href='holds'><img src="[% ctx.media_prefix %]/images/sub_holds_off.jpg"/></a>
+        </div>
+        <div class="align">
+            <img src="[% ctx.media_prefix %]/images/sub_holds_hist_on.jpg"/>
+        </div>
+        <div class="clear-both"></div>
+    </div>
+
+    <div class="header_middle">
+        <span style="float:left;">[% l("Previously Held Items") %]</span>
+        <span class='float-left' style='padding-left: 10px;'>
+            <a href='hold_history?limit=[% limit %]&amp;offset=[% offset - limit %]'
+                [% IF offset == 0 %] class='invisible' [% END %]><span class="nav_arrow_fix">&#9668;</span>[% l('Previous') %]</a>
+            [%# TODO: get total to prevent paging off then end of the list.. %]
+            <a href='hold_history?limit=[% limit %]&amp;offset=[% offset + limit %]'
+               [% IF ctx.holds.size < limit %] class='invisible' [% END %] >[% l('Next') %]<span class="nav_arrow_fix">&#9658;</span></a>
+        </span>
+        <span style="float:right;">
+            <a class="hide_me" href="#">Export List</a>
+        </span>
+    </div>
+    <div class="clear-both"></div>
+
+    <div id='holds_main'>
+        [% IF ctx.holds.size < 1 %]
+        <div class="opac-auto-079">
+            <big><strong>[% l('No holds found.') %]</strong></big>
+        </div>
+        [% ELSE %]
+        <table style='border-collapse:collapse; width: 100%;'>
+            <thead id='acct_holds_main_header'>
+                <tr>
+                    <td width="138"><span>[% l('Title') %]</span></td>
+                    <td width="123"><span>[% l('Author') %]</span></td>
+                    <td width="64"> <span>[% l('Format') %]</span></td>
+                    <td width="136"><span>[% l('Pickup Location') %]</span> </td>
+                    <td width="104">[% l('Active On') %]</td>
+                    <td width="95">[% l('Active') %]</td>
+                    <td width="106">[% l('Date Fulfilled') %]</td>
+                    <td width="172"><span>[% l('Status') %]</span></td>
+                </tr>
+            </thead>
+            <tbody>
+                [% FOR hold IN ctx.holds;
+                    attrs = {marc_xml => hold.marc_xml};
+                    PROCESS get_marc_attrs args=attrs;
+                    ahr = hold.hold.hold %]
+
+                <tr id="acct_holds_temp" name="acct_holds_temp" class="acct_holds_temp">
+
+                    <td width="138">
+                        <div style="margin-top:10px;margin-bottom:10px;">
+                            <a href="[% ctx.opac_root %]/record/[% hold.hold.bre.id %]">[% attrs.title | html %]</a>
+                        </div>
+                    </td>
+                    <td width="123">
+                        <div style="margin-top:10px;margin-bottom:10px;">
+                            <a href="[% ctx.opac_root %]/results?qtype=author&amp;query=[% attrs.author | replace('[,\.:;]', '') | url %]">[% attrs.author | html %]</a>
+                        </div>
+                    </td>
+                    <td width="64">
+                        <div style="width:26px;height:23px;margin-top:6px;margin-bottom:6px;">
+                            [% IF attrs.format_icon %]
+                            <img src="[% ctx.media_prefix %]/images/[% attrs.form_icon %]"
+                                title="[% attrs.format %]" alt="[% attrs.format %]" />
+                            [% ELSE;
+                                attrs.format;
+                               END %]
+                        </div>
+                    </td>
+                    <td width="136">
+                        [% ctx.get_aou(ahr.pickup_lib).name %]
+                    </td>
+                    <td width="104">
+                        [% IF ahr.frozen == 't' AND ahr.thaw_date;
+                            date.format(ctx.parse_datetime(ahr.thaw_date), DATE_FORMAT);
+                        END %]
+                    </td>
+                    <td width="95">
+                        [% l(ahr.frozen == 'f' ? 'Active' : 'Suspended') %]
+                    </td>
+                    <td width="106">
+                        [% IF ahr.fulfillment_time;
+                            date.format(ctx.parse_datetime(ahr.fulfillment_time), DATE_FORMAT);
+                        END %]
+                    </td>
+                    <td width="110">
+                        <div name="acct_holds_status"
+                            style="margin-top:10px;margin-bottom:10px;">
+                            [%
+                                IF hold.hold.status == 4;
+                                    l("Available");
+                                    IF ahr.shelf_expire_time;
+                                        l('<br/>Expires [_1]', 
+                                            date.format(ctx.parse_datetime(ahr.shelf_expire_time), DATE_FORMAT));
+                                    END;
+                                ELSIF hold.hold.estimated_wait AND hold.hold.estimated_wait > 0;
+                                    # estimated wait is delivered as seconds.
+                                    SET hwait = POSIX.ceil(hold.hold.estimated_wait / 86400);
+                                    l("Estimated wait: [quant,_1,day,days]", hwait);
+                                ELSIF hold.hold.status == 3;
+                                    l("In Transit");
+                                ELSIF hold.hold.status < 3;
+                                    l("Waiting for copy");
+                                END;
+                            %]
+                        </div>
+                    </td>
+                </tr>
+                [% END %]
+            </tbody>
+        </table>
+        [% END %]
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/holds.tt2 b/Open-ILS/web/templates/default/opac/myopac/holds.tt2
new file mode 100644 (file)
index 0000000..a6bb670
--- /dev/null
@@ -0,0 +1,228 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+    myopac_page = "holds"  %]
+<div id='myopac_holds_div'>
+
+    <div id="acct_holds_tabs" style="padding-bottom: 12px;color:#666;">
+        <div class="align selected">
+            <img src="[% ctx.media_prefix %]/images/sub_holds_on.jpg"/>
+        </div>
+        <div class="align">
+            <a href='hold_history'><img src="[% ctx.media_prefix %]/images/sub_holds_hist_off.jpg"/></a>
+        </div>
+        <div class="clear-both"></div>
+    </div>
+
+    <div class="header_middle">
+        <span id="acct_holds_header" style="float:left;">
+            [%  IF CGI.param("available");
+                    l("Items Ready for Pickup");
+                ELSE;
+                    l("Current Items on Hold");
+                END
+            %]
+        </span>
+        <span style="float:right;">
+            <a class="hide_me" href="#">Export List</a>
+        </span>
+    </div>
+    <div class="clear-both"></div>
+    <div id='holds_main'>
+        <form method="POST">
+        <table cellpadding='0' cellspacing='0' class="opac-auto-097">
+            <tr>
+                <td width="1">
+                    <select name="action" id="acct_holds_actions">
+                        <option id='myopac_holds_actions_none' value=''>
+                        -- [% l("Actions for selected holds") %] --
+                        </option>
+                        <option value='suspend'>
+                            [% l("Suspend") %]
+                        </option>
+                        <option value='activate'>
+                            [% l("Activate") %]
+                        </option>
+                        <!-- XXX maybe later <option value='thaw_date'>
+                            [% l("Set Active Date") %]
+                        </option> -->
+                        <option value='cancel'>
+                            [% l("Cancel") %]
+                        </option>
+                    </select>
+                </td>
+                <td width="1" style="padding-left:9px;">
+                    <input type="image"
+                        alt="[% l('Go') %]" title="[% l('Go') %]"
+                        src="[% ctx.media_prefix %]/images/go-btn.png" />
+                </td>
+                <td width="1" style="padding-left:5px;">
+                    <a href="#"><img
+                        alt="Holds Help"
+                        src="[% ctx.media_prefix %]/images/question-mark.png" /></a>
+                </td>
+                <td align="right">
+                    [% l("Show") %] &nbsp; &nbsp;
+                    [% IF CGI.param("available") %]
+                    <a href="holds">[% l('all') %]</a> |
+                    <strong>[% l("only available") %]</strong>
+                    [% ELSE %]
+                    <strong>[% l("all") %]</strong> |
+                    <a href="holds?available=1">[% l("only available") %]</a>
+                    [% END %] &nbsp; &nbsp;
+                    [% l("holds") %]
+                    <select class="hide_me" id="holds_sort">
+                        <option value="">-- Sort By --</option>
+                        <option value="title">Title</option>
+                        <option value="pickup">PickUp Location</option>
+                        <option value="status">Status</option>
+                    </select>
+                </td>
+            </tr>
+        </table>
+        [% IF ctx.holds.size < 1 %]
+        <div class="opac-auto-079">
+            <big><strong>[% l('No holds found.') %]</strong></big>
+        </div>
+        [% ELSE %]
+        <table id="acct_holds_main_header" cellpadding='0' cellspacing='0'
+            border='0' width="100%">
+            <tr>
+                <td width="36" align="center">
+                    <input type="checkbox" id="check_all_holds" />
+                </td>
+                <td width="138">
+                    <span title="Click to sort"
+                        style="cursor:pointer;">
+                        Title
+                    </span>
+                </td>
+                <td width="123">
+                    <span title="Click to sort" style="cursor:pointer;">Author</span>
+                </td>
+                <td width="64">
+                    <span title="Click to sort"
+                        style="cursor:pointer;">Format</span>
+                </td>
+                <td width="136">
+                    <span title="Click to sort"
+                        style="cursor:pointer;">Pickup Location</span>
+                </td>
+                <td width="104">Activate</td>
+                <td width="106">Cancel if not<br />filled by</td>
+                <td width="95">Active</td>
+                <td width="172">
+                    <span title="Click to sort"
+                        style="cursor:pointer;">Status</span>
+                </td>
+            </tr>
+        </table>
+        <div class="hide_me">
+            <select id="hold_pickup_lib_temp" name="hold_pickup_lib_sel"
+                class="hide_me" style="width:125px;height:21px;"></select>
+        </div>
+
+        <table cellpadding='0' cellspacing='0' border='0' width="100%">
+            <tbody id="holds_temp_parent">
+                [% FOR hold IN ctx.holds;
+                    attrs = {marc_xml => hold.marc_xml};
+                    PROCESS get_marc_attrs args=attrs;
+                    ahr = hold.hold.hold %]
+                <tr id="acct_holds_temp" name="acct_holds_temp"
+                    class="acct_holds_temp">
+                    <td width="36" align="center" style="text-align:center;">
+                        <input type="checkbox" name="hold_id" value="[% ahr.id %]" />
+                    </td>
+                    <td width="138">
+                        <div style="margin-top:10px;margin-bottom:10px;">
+                            <a href="[% ctx.opac_root %]/record/[% hold.hold.bre.id %]">[% attrs.title | html %]</a>
+                        </div>
+                    </td>
+                    <td width="123">
+                        <div style="margin-top:10px;margin-bottom:10px;">
+                            <a href="[% ctx.opac_root %]/results?qtype=author&amp;query=[% attrs.author | replace('[,\.:;]', '') | url %]">[% attrs.author | html %]</a>
+                        </div>
+                    </td>
+                    <td width="64">
+                        <div style="width:26px;height:23px;margin-top:6px;margin-bottom:6px;">
+                            [% IF attrs.format_icon %]
+                            <img src="[% ctx.media_prefix %]/images/[% attrs.form_icon %]"
+                                title="[% attrs.format %]" alt="[% attrs.format %]" />
+                            [% ELSE;
+                                attrs.format;
+                               END %]
+                        </div>
+                    </td>
+                    <td width="136">
+                        [% ctx.get_aou(ahr.pickup_lib).name %]
+                    </td>
+                    <td width="104">
+                        <!-- <input
+                            title="Enter a date (e.g. 10/21/2010)"
+                            class="hide_me" style="width:91px;"
+                            name="activate_box" type="text" /> -->
+                        [% IF ahr.frozen == 't' AND
+                                ahr.thaw_date;
+                            date.format(ctx.parse_datetime(ahr.thaw_date), DATE_FORMAT);
+                        END %]
+                    </td>
+                    <td width="106">
+                        <!-- <input title="[% l('Enter a date (e.g. 10/21/2010)') %]"
+                            class="hide_me" style="width:91px;"
+                            name="hold_expires_box" type="text" />-->
+                        [% IF ahr.expire_time;
+                            date.format(ctx.parse_datetime(ahr.expire_time), DATE_FORMAT);
+                        END %]
+                    </td>
+                    <td width="95">
+                        <!-- <select name="hold_active_sel"
+                            style="width:90px;" class="hide_me">
+                            <option value="f">Active</option>
+                            <option value="t">Suspended</option>
+                        </select> -->
+                        [% l(ahr.frozen == 'f' ? 'Active' : 'Suspended') %]
+                    </td>
+                    <td width="110">
+                        <div name="acct_holds_status"
+                            style="margin-top:10px;margin-bottom:10px;">
+                            [% PROCESS get_hold_status hold=hold; %]
+                        </div>
+                    </td>
+                    <td class="opac-auto-161">
+                        <a href="[% ctx.opac_root %]/myopac/holds/edit?id=[% ahr.id %]">Edit</a>
+                    </td>
+                </tr>
+                [% END %]
+            </tbody>
+        </table>
+        [% END %]
+        </form>
+    </div>
+
+    <span id='myopac.holds.cancel.confirm' class='hide_me'>[% l("Are you sure you wish to cancel the selected holds?") %]</span>
+    <span id='myopac.holds.freeze.confirm' class='hide_me'>[% l("Are you sure you wish to suspend the selected holds?  If an item has already been selected to fulfill the hold, it will not be suspended") %]</span>
+    <span id='myopac.holds.thaw.confirm' class='hide_me'>[% l("Are you sure you wish to activate the selected holds?") %]</span>
+    <span id='myopac.holds.thaw_date.confirm' class='hide_me'>[% l("Are you sure you wish to change the activate date for the selected holds?") %]</span>
+    <span id='myopac.holds.freeze.select_thaw' class='hide_me'>[% l("Select an automatic activation date.  If no date is chosen, the holds will remain suspended until they are manually activated.") %]</span>
+
+    <table width='100%' id='myopac_holds_processing' class='hide_me'>
+        <tr><td>[% l("Processing holds... This may take a moment.") %]</td></tr>
+    </table>
+   
+    <span class='hide_me' id='myopac_holds_cancel_verify'>
+       [% l("If you wish to cancel the selected hold, click OK, otherwise click Cancel.") %]
+    </span>
+</div>
+<div id='myopac_holds_thaw_date_form' class='hide_me'>
+    <div id='myopac_holds_freeze_select_thaw'>
+        [% l("Select an automatic activation date.  If no date is chosen, the holds will remain suspended until they are manually activated.") %]
+    </div>
+    <p>
+        <input size='10' maxlength='10'
+            type='text' id='myopac_holds_thaw_date_input' />
+    </p>
+    <p>
+        <button>[% l("Submit") %]</button>
+    </p>
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/holds/edit.tt2 b/Open-ILS/web/templates/default/opac/myopac/holds/edit.tt2
new file mode 100644 (file)
index 0000000..53e12c9
--- /dev/null
@@ -0,0 +1,117 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    PROCESS "default/opac/parts/org_selector.tt2";
+    WRAPPER "default/opac/parts/base.tt2" +
+        "default/opac/parts/myopac/base.tt2";
+    myopac_page = "holds"; # in this case, just for tab coloring.
+
+    hold = 0;
+    FOR h IN ctx.holds;
+        IF h.hold.hold.id == CGI.param('id');
+            hold = h;
+            ahr = hold.hold.hold;
+            attrs = {marc_xml => hold.marc_xml};
+            PROCESS get_marc_attrs args=attrs;
+            hold.human_status = PROCESS get_hold_status hold=hold;
+
+            # Do this up front to avoid verbosity later
+            expire_time = ahr.expire_time ? date.format(ctx.parse_datetime(ahr.expire_time), DATE_FORMAT) : '';
+            thaw_date = ahr.thaw_date ? date.format(ctx.parse_datetime(ahr.thaw_date), DATE_FORMAT) : '';
+            LAST;
+        END;
+    END;
+%]
+<div class="pad-bottom-five">
+    <div class="header_middle">
+        <span id="acct_holds_header float-left">[% l('Editing Hold') %]</span>
+        &nbsp; &nbsp; &nbsp; &nbsp;
+        <a href="[% ctx.opac_root %]/myopac/holds">[% l('List all holds') %]</a>
+    </div>
+    <div id="hold_editor">
+        [% IF hold %]
+            <h1>[% attrs.title %]</h1>
+            <h2>[% attrs.author %]</h2>
+            [% IF attrs.format_icon %]<p>
+                <strong>[% l('Format:') %]</strong>
+                <img src="[% ctx.media_prefix %]/images/[% attrs.format_icon %]" alt="[% attrs.format %]" title="[% attrs.title %]" />
+            </p>[% END %]
+            <p>
+                <strong>[% l('Status') %]</strong>: [% hold.human_status %]
+            </p>
+            <form method="POST">
+                <table id="hold_editor_table">
+                    <tr>
+                        <th>
+                            <input type="hidden" name="action" value="edit" />
+                            <input type="hidden" name="hold_id"
+                                value="[% ahr.id %]" />
+                            [% l('Pickup library') %]
+                        </th>
+                        <td>
+                            [% PROCESS build_org_selector
+                                name='pickup_lib' value=ahr.pickup_lib %]
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>
+                            [% l('Cancel unless filled by') %]
+                        </th>
+                        <td>
+                            <input type="text" name="expire_time"
+                                value="[% expire_time | html %]" />
+                        </td>
+                        <td class="fmt-note">
+                            <em>[% l('Enter date in MM/DD/YYYY format') %]</em>
+                            <!-- XXX TODO pick out a minimal, simple, reliable
+                            calendar widget that's not part of some giant,
+                            bloated framework and doesn't do anything at onload.
+                            -->
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>
+                            [% l('Active?') %]
+                        </th>
+                        <td>
+                            <select name="frozen">
+                                <option value="f"[% ahr.frozen == 't' ? '' :' selected="selected"' %]>
+                                    [% l('Yes, this hold is active now') %]
+                                </option>
+                                <option value="t"[% ahr.frozen == 't' ? ' selected="selected"' : '' %]>
+                                    [% l('No, this hold is suspended') %]
+                                </option>
+                            </select>
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>
+                            [% l('If suspended, activate on') %]
+                        </th>
+                        <td>
+                            <input type="text" name="thaw_date"
+                                value="[% thaw_date | html %]" />
+                        </td>
+                        <td class="fmt-note">
+                            <em>[% l('Enter date in MM/DD/YYYY format') %]</em>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td colspan="2" class="hold-editor-controls">
+                            <input type="image"
+                                src="[% ctx.media_prefix %]/images/btnSubmit.png"
+                                alt="[% l('Submit') %]"
+                                title="[% l('Submit') %]" />
+                            <a href="[% ctx.opac_root %]/myopac/holds"><img
+                                src="[% ctx.media_prefix %]/images/btnCancel.png"
+                                alt="[% l('Cancel') %]"
+                                title="[% l('Cancel') %]" /></a>
+                        </td>
+                    </tr>
+                </table>
+            </form>
+        [% ELSE;
+            l('Hold not found');
+        END %]
+    </div>
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/lists.tt2 b/Open-ILS/web/templates/default/opac/myopac/lists.tt2
new file mode 100644 (file)
index 0000000..ba8d556
--- /dev/null
@@ -0,0 +1,185 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+    myopac_page = "lists"  %]
+<div id='myopac_bookbag_div' style="padding:5px;">
+
+    <!-- <div class="header_middle">
+        <span id="acct_holds_header" style="float:left;">[% l('My Lists') %]</span>
+        <span style="float:right;"><a class="hide_me" href="#">[% l('Export List') %]</a></span>
+    </div>
+    <div style="float:right;width:85px;">
+        <div style="position:absolute">
+            <div style="position:relative;top:13px;">
+                <a href="#" style="position:relative;top:-3px;left:-5px;"><img alt="[% l('Saving Help') %]" 
+                    src="[% ctx.media_prefix %]/images/question-mark.png" /></a>
+                <a href="#"><img alt="[% l('Save') %]" src="[% ctx.media_prefix %]/images/save-btn.png"/></a>
+            </div>
+        </div>
+    </div> -->
+    <div id="temp_wrapper">
+
+
+    <!-- new list creation -->
+    <form action="[% ctx.opac_root %]/myopac/list/update" method="POST" id="create_form">
+        <h2>[% l('Create new list') %]</h2><a name="createnewlist"></a>
+        <table cellpadding="0" border="0" id="list_create_table">
+            <tr>
+                <td>
+                    <label for="list_create_name">[% l('Enter the name of the new list:') %]</label>
+                    <input id="list_create_name" type="text" name="name" />
+                    <input type="hidden" name="action" value="create" />
+                </td>
+                <td>
+                    <label for="list_create_shared">[% l('Share this list?') %]</label>
+                    <select name="shared" id="list_create_shared">
+                        <option value="0">[% l('No') %]
+                        <option value="1">[% l('Yes') %]
+                    </select>
+                    <a href="javascript:void(0);" onclick="alert(document.getElementById('bb_publish_text').innerHTML);"><img alt="[% l('Sharing Help') %]"
+                        src="[% ctx.media_prefix %]/images/question-mark.png" /></a>
+                </td>
+                <td class="list-create-table-buttons">
+                    <input type="image" alt="[% l('Submit') %]" src="[% ctx.media_prefix %]/images/btnSubmit.png"/>
+                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+                    <a href="javascript:void(0);"
+                        onclick="document.getElementById('create_form').reset(); return false"><img
+                        alt="[% l('Cancel') %]"
+                        src="[% ctx.media_prefix %]/images/btnCancel.png" /></a>
+                </td>
+            </tr>
+        </table>
+    </form>
+
+    [% INCLUDE "default/opac/parts/anon_list.tt2" %]
+    [% IF ctx.bookbags.size %]
+    <div id='acct_lists_prime'>
+        [% FOR bbag IN ctx.bookbags %]
+        <div id='acct_list_template'>
+            <div style="width:100%">
+                <form action="[% ctx.opac_root %]/myopac/list/update" method="POST">
+                    <div class="bookbag-share">
+                        <input type="hidden" name="list" value="[% bbag.id %]" />
+                        [% IF bbag.pub != 't' %]
+                        <input type="hidden" name="action" value="show" />
+                        <input type="submit" value="[% l('Share') %]" />
+                        [% ELSE %]
+                        <input type="hidden" name="action" value="hide" />
+                        <input type="submit" value="[% l('Hide') %]" />
+                        [% END %]
+                    </div>
+                </form>
+                <form action="[% ctx.opac_root %]/myopac/list/update" method="POST">
+                    <div class="bookbag-controls">
+                        <input type="hidden" name="list" value="[% bbag.id %]" />
+                        <input type="hidden" name="action" value="delete" />
+                        <input type="submit" value="[% l('Delete List') %]" />
+                    </div>
+                </form>
+                <div class="bookbag-controls">
+                    <big><strong>
+                    [% IF bbag.pub == 't' %]
+                        [% url = 'http://' _ ctx.hostname _ '/opac/extras/feed/bookbag/html-full/' _ bbag.id %]
+                        <a target='_blank' href='[% url %]'>[% bbag.name %]</a>
+                    [% ELSE %]
+                    [% bbag.name %]
+                    [% END %]
+                    </strong></big>
+                </div>
+                <div class="bookbag-controls">
+                    [% IF bbag.pub == 't'; %]
+                    <a target='_blank' href='/opac/extras/feed/bookbag/rss2-full/[% bbag.id %]'><img
+                        alt="[% l('RSS Feed') %]" border="0"
+                        src="[% ctx.media_prefix %]/images/small-rss.png"/></a>
+                    [% END %]
+                </div>
+                <div class="clear-both pad-bottom-five"></div>
+            </div>
+            <form action="[% ctx.opac_root %]/myopac/list/update" method="POST">
+            <input type="hidden" name="list" value="[% bbag.id %]" />
+            <table cellpadding='0' cellspacing='0' border='0'>
+                <thead id="acct_list_header">
+                    <tr>
+                        <td width="1%" style="padding-left: 10px;">
+                        <input type="checkbox" onclick="
+                            var inputs=document.getElementsByTagName('input'); 
+                            for (i = 0; i < inputs.length; i++) { 
+                                if (inputs[i].name == 'del_item' && !inputs[i].disabled && inputs[i].getAttribute('bbag') == [% bbag.id %]) 
+                                    inputs[i].checked = this.checked;}"/>
+
+                        </td>
+                        <td width="49%" style="padding-left: 5px;">[% l('Title') %]</td>
+                        <td width="49%">[% l('Author(s)') %]</td>
+                        <td width="1%" class="nowrap">
+                            <select class="opac-auto-179" name="action">
+                                <option>[% l('-- Actions for this list --') %]</option>
+                                <!-- XXX not ready yet<option value="hold">[% l('Place Hold') %]</option> -->
+                                <option value="del_item">[% l('Remove Items') %]</option>
+                            </select>
+                            <input type="submit" value="[% l('Go') %]" />
+                        </td>
+                    </tr>
+                </thead>
+                <tbody>
+                    [% UNLESS bbag.items.size %]
+                    <tr><td colspan="4" class="opac-auto-171 opac-auto-097">
+                        [% l("This list contains no items.") %]
+                    </td></tr>
+                    [% END %]
+                    [% FOR item IN bbag.items;
+                        rec_id = item.target_biblio_record_entry;
+                        attrs = {marc_xml => ctx.bookbags_marc_xml.$rec_id};
+                        PROCESS get_marc_attrs args=attrs %]
+                    <tr>
+                        <td class="opac-auto-097b" style="padding-left: 10px;"><input type="checkbox" name="del_item" value="[% item.id %]" bbag='[% bbag.id %]'/></td>
+                        <td class="opac-auto-097b" style="padding-left: 5px;">[% attrs.title %]</td>
+                        <td class="opac-auto-097b">[% attrs.author %]</td>
+                    </tr>
+                    [% END %]
+                </tbody>
+            </table>
+            </form>
+            <br /><br />
+        </div>
+        [% END %]
+    </div>
+    [% END %]
+
+    <div id='myopac_delete_bookbag_warn' class='hide_me'>
+        [% l("This will remove the selected bookbag and all items contained within the bookbag.  Are you sure you wish to continue?") %]
+    </div>
+    <div style='text-align: center; font-weight: bold;' 
+        class='hide_me' id='myopac_bookbags_none'>[% l("You have not created any bookbags") %]</div>
+    <div style='width: 99%; text-align: center'>
+        <b id='myopac_bookbag_items_name'> </b>
+    </div>
+    <span id='bb_publish_text' class='hide_me'>
+[% |l %]Sharing a Bookbag means that the contents 
+of the Bookbag will be visible to others.  
+To see the public view of a shared Bookbag, 
+click on the Bookbag's name in the Bookbag list.[% END %]
+    </span>
+    <span id='myopac_remove_bb_item_confirm' class='hide_me'>
+        [% l("Are you sure you wish to remove this bookbag item?") %]
+    </span>
+    <span id='myopac_make_published_confirm' class='hide_me'>
+        [% l("Sharing this bookbag will allow the contents of the bookbag to be seen by others.  Are you sure you wish to share this bookbag?") %]
+    </span>
+    <span id='myopac_make_unpublished_confirm' class='hide_me'>
+        [% l("Are you sure you wish to hide this bookbag?") %]
+    </span>
+    <span id='myopac_bb_update_success' class='hide_me'>
+        [% l("The Bookbag was successfully updated.") %]
+    </span>
+    <span id='bb_create_warning' class='hide_me'>
+        [% l("Warning: Adding items to a bookbag creates a link between you and the items in the database.  The contents of the bookbag are NOT publicly viewable unless the bookbag is shared. However, if you prefer not to have any link between your patron record and a particular item or items, we suggest that you do not place said items in a bookbag or that you avoid using bookbags all together.  Thank you.") %]
+    </span>
+    <span id='myopac_bb_what_are' class='hide_me'>
+        [% l("Bookbags are...") %]
+    </span>
+    <span class='hide_me' id='bb_update_success'>
+        [% l("Bookbag successfully updated") %]
+    </span>
+
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/main.tt2 b/Open-ILS/web/templates/default/opac/myopac/main.tt2
new file mode 100644 (file)
index 0000000..3a4bc04
--- /dev/null
@@ -0,0 +1,163 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/main_base.tt2";
+    myopac_page = "main";
+    myopac_main_page = "main";
+%]
+<form action="[% ctx.opac_root %]/myopac/main_payment_form" method="POST">
+    [% IF ctx.fines.circulation.size > 0 %]
+    <div id='myopac_circ_trans_div'>
+        <table width='100%' class='data_grid'>
+            <thead>
+                <tr>
+                    <td colspan='10' style='padding: 6px'>
+                        <strong>[% l("Fines") %]</strong>
+                    </td>
+                </tr>
+                <tr>
+                    <td>[% l("Title") %]</td>
+                    <td>[% l("Author") %]</td>
+                    <td>[% l("Checkout Date") %]</td>
+                    <td>[% l("Due Date") %]</td>
+                    <td>[% l("Date Returned") %]</td>
+                    <td>[% l("Balance Owed") %]</td>
+                    <td nowrap="nowrap" style="white-space:nowrap;">
+                        <!-- XXX TODO select all js --><input id="pay_fines_box1" checked="checked"
+                            type="checkbox" title="[% l('Click to (un)select all fines') %]" />
+                        <label for="pay_fines_box1">[% l('Pay Fines') %]</label>
+                    </td>
+                </tr>
+            </thead>
+            <tbody id='myopac_circ_trans_tbody'>
+                [% FOR f IN ctx.fines.circulation;
+                    attrs = {marc_xml => f.marc_xml};
+                    IF f.marc_xml;
+                        PROCESS get_marc_attrs args=attrs;
+                    ELSIF f.xact.reservation;
+                        attrs.title = f.xact.reservation.target_resource_type.name;
+                    END %]
+                <tr id='myopac_circ_trans_row'>
+                    <td>
+                        [% recid = f.xact.circulation.target_copy.call_number.record.id || f.xact.reservation.target_resource_type.record.id;
+                        IF recid; %]
+                        <a href="[% ctx.opac_root %]/record/[% recid %]">[% attrs.title %]</a>
+                        [% ELSE %]
+                        [% attrs.title %]
+                        [% END %]
+                    </td>
+                    <td>
+                        <a href="[% ctx.opac_root %]/results?qtype=author&amp;query=[% attrs.author | replace('[,\.:;]', '') | url %]">[% attrs.author %]</a>
+                    </td>
+                    <td name='myopac_circ_trans_start'>
+                        [% ts = f.xact.circulation.xact_start || f.xact.reservation.start_time || 0;
+                        IF ts;
+                            date.format(ctx.parse_datetime(ts), DATE_FORMAT);
+                        END %]
+                    </td>
+                    <td name='myopac_circ_trans_due'>
+                        [% ts = f.xact.circulation.due_date || f.xact.reservation.end_time || 0;
+                        IF ts;
+                            date.format(ctx.parse_datetime(ts), DATE_FORMAT);
+                        END %]
+                    </td>
+                    <td name='myopac_circ_trans_finished'>
+                        [%  ts = f.xact.circulation.checkin_time || f.xact.reservation.return_time || 0;
+                            IF ts;
+                                date.format(ctx.parse_datetime(ts), DATE_FORMAT);
+                            ELSE %]
+                            <!-- XXX TODO fines aren't really accruing
+                                if circ has hit maxfines. more clarity
+                                here? -->
+                            <span class="red">[% l('(fines accruing)') %]</span>
+                        [%  END %]
+                    </td>
+                    <td>
+                        <strong class="red">
+                            [% money(f.xact.balance_owed) %]
+                        </strong>
+                    </td>
+                    <td>
+                        <input type="checkbox" title="[% l('Pay this fine') %]"
+                            name="xact" value="[% f.xact.id %]" />
+                    </td>
+                </tr>
+                [% END %]
+            </tbody>
+        </table>
+    </div>
+    [% END %]
+
+    [% IF ctx.fines.grocery.size > 0 %]
+    <!-- Table for all non-circulation transactions -->
+    <div id='myopac_trans_div'>
+        <br/>
+        <hr class='opac-auto-013'  color="#dcdbdb" />
+        <br/>
+        <table width='100%' class='data_grid data_grid_center'
+            id='myopac_trans_table'>
+            <thead>
+                <tr>
+                    <td colspan='8' style='padding: 6px'>
+                        <b>[% l("Other Fees") %]</b>
+                    </td>
+                </tr>
+                <tr>
+                    <td width='16%'>[% l("Transaction Start Time") %]</td>
+                    <td width='16%'>[% l("Last Payment Time") %]</td>
+                    <td width='16%'>[% l("Initial Amount Owed") %]</td>
+                    <td width='16%'>[% l("Total Amount Paid") %]</td>
+                    <td width='16%'>[% l("Balance Owed") %]</td>
+                    <td width='16%'>[% l("Billing Type") %]</td>
+                    <td width='4%' align="center" nowrap="nowrap"
+                        style="white-space:nowrap;">
+                        <input id="pay_fines_box2" checked="checked"
+                            type="checkbox"
+                            title="[% l('Click to (un)select all fines') %]" />
+                        <label for="pay_fines_box2">[% l("Pay Fines") %]</label>
+                    </td>
+                </tr>
+            </thead>
+            <tbody id='myopac_trans_tbody'>
+                [% FOR f IN ctx.fines.grocery %]
+                <tr id='myopac_trans_row'>
+                    <td>[% date.format(
+                            ctx.parse_datetime(f.xact.xact_start),
+                            DATE_FORMAT
+                    ) %]</td>
+                    <td>
+                        [%  IF f.xact.last_payment_ts;
+                                date.format(
+                                    ctx.parse_datetime(
+                                        f.xact.last_payment_ts
+                                    ), DATE_FORMAT
+                                );
+                            END %]
+                    </td>
+                    <td>[% money(f.xact.total_owed) %]</td>
+                    <td>[% money(f.xact.total_paid) %]</td>
+                    <td class="red">
+                        <strong>
+                            [% money(f.xact.balance_owed) %]
+                        </strong>
+                    </td>
+                    <td>[% f.xact.last_billing_type %]</td>
+                    <td>
+                        <input type="checkbox" title='[% l("Pay this fine") %]'
+                            name="xact" value="[% f.xact.id %]" />
+                    </td>
+                </tr>
+                [% END %]
+            </tbody>
+        </table>
+    </div>
+    [% END %]
+    <div class="text-right pad-top-ten">
+        <input type="image"
+            alt="[% l('Pay selected fines') %]"
+            title="[% l('Pay selected fines') %]"
+            onmouseover="this.src='[% ctx.media_prefix %]/images/pay-fines-btn-hover.png';"
+            onmouseout="this.src='[% ctx.media_prefix %]/images/pay-fines-btn.png';"
+            src="[% ctx.media_prefix %]/images/pay-fines-btn.png" />
+    </div>
+</form>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/main_payment_form.tt2 b/Open-ILS/web/templates/default/opac/myopac/main_payment_form.tt2
new file mode 100644 (file)
index 0000000..b054f46
--- /dev/null
@@ -0,0 +1,169 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/main_base.tt2";
+    myopac_page = "main";
+    myopac_main_page = "payment_form";
+%]
+[% IF ctx.fines.balance_owed <= 0 %]
+<div>
+    [% l("You either have no fines to pay or you have selected fines whose " _
+        "total is non-positive.  We cannot process non-positive amounts.") %]
+</div>
+[% ELSE %]
+<div id="pay_fines_now">
+    <form action="[% ctx.opac_root %]/myopac/pay" method="POST"
+        onsubmit="return confirm('[% l("Are you sure you are ready to charge [_1] to your credit card?", money(ctx.fines.balance_owed)) %]');">
+        [% FOR xact IN CGI.param('xact') %]
+        <input type="hidden" name="xact" value="[% xact | html %]" />
+        [% END %]
+        <table>
+            <tbody>
+                <tr>
+                    <td colspan='2'><strong>[% l('Billing Information') %]</strong></td>
+                    <td rowspan='13' valign='top'>
+                        [% l('Selected fines you are paying for:') %]
+                        <table cellpadding="0" cellspacing="5" border="0">
+                            <thead>
+                                <tr>
+                                    <th>[% l('Name') %]</th>
+                                    <th>[% l('Amount') %]</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                            [%
+                            FOR f IN ctx.fines.circulation;
+                                NEXT IF CGI.param('xact').size &&
+                                    !CGI.param('xact').grep(f.xact.id).size;
+                                attrs = {marc_xml => f.marc_xml};
+                                IF f.marc_xml;
+                                    PROCESS get_marc_attrs args=attrs;
+                                ELSIF f.xact.reservation;
+                                    attrs.title = f.xact.reservation.target_resource_type.name;
+                                END %]
+                                <tr>
+                                    <td>[% attrs.title %]</td>
+                                    <td class="text-right">[% money(f.xact.balance_owed) %]</td>
+                                </tr>
+                            [%
+                            END;
+                            FOR f IN ctx.fines.grocery;
+                                NEXT IF CGI.param('xact').size &&
+                                    !CGI.param('xact').grep(f.xact.id).size %]
+                                <tr>
+                                    <td>[% f.xact.last_billing_type %]</td>
+                                    <td class="text-right">[% money(f.xact.balance_owed) %]</td>
+                                </tr>
+                            [% END %]
+                            </tbody>
+                        </table>
+                        <br />
+                        <div>
+                            [% l('Total amount to pay:') %]
+                            <strong>[% money(ctx.fines.balance_owed) %]</strong>
+                        </div>
+                        <br />
+                        [% | l('<strong>', '</strong>') %]Click [_1]Cancel[_2] to go back and (un)select other fines.[% END %]
+                    </td>
+                </tr>
+                <tr>
+                    <td>[% l('First Name') %]</td>
+                    <td><input type="text" name="billing_first" value="[% ctx.user.first_given_name | html %]" /></td>
+                </tr>
+                <tr>
+                    <td>[% l('Last Name') %]</td>
+                    <td><input type="text" name="billing_last" value="[% ctx.user.family_name | html %]" /></td>
+                </tr>
+                <tr>
+                    <td>[% l('Street Address') %]</td>
+                    <td><input type="text" name="billing_address" value="[% ctx.user.billing_address.street1 _ ctx.user.billing_address.street2 | html %]" /></td>
+                </tr>
+                <tr>
+                    <td>[% l('City' )%]</td>
+                    <td><input type="text" name="billing_city" value="[% ctx.user.billing_address.city | html %]" /></td>
+                </tr>
+                <tr>
+                    <td>[% l('State or Province') %]</td>
+                    <td><input type="text" name="billing_state" value="[% ctx.user.billing_address.state | html %]" /></td>
+                </tr>
+                <tr>
+                    <td>[% l('ZIP or Postal Code') %]</td>
+                    <td><input type="text" name="billing_zip" value="[% ctx.user.billing_address.post_code | html %]" /></td>
+                </tr>
+                <tr>
+                  <td colspan='2'><strong>[% l('Credit Card Information') %]</strong></td>
+                </tr>
+                <!-- Technically not needed since card type is derived from the CC number
+                <tr>
+                    <td>Type of Card</td>
+                    <td>
+                        <select name="type">
+                            <option value='VISA'>VISA</option>
+                            <option value='MasterCard'>MasterCard</option>
+                            <option value='American Express'>American Express</option>
+                        </select>
+                    </td>
+                </tr>
+                -->
+                <tr>
+                    <td>[% l('Credit Card #') %]</td>
+                    <td><input type="text" name="number" maxlength="16" /></td>
+                </tr>
+                <tr>
+                    <td>
+                        <div style="position:absolute;">
+                            <div style="position:relative;left:80px;">
+                                <a href="#"><img
+                                    src="[% ctx.media_prefix %]/images/question-mark.png" /></a>
+                            </div>
+                        </div>
+                        [% l('Security Code') %]
+                    </td>
+                    <td>
+                        <input type="text" size="4" maxlength="5" name="cvv2" />
+                    </td>
+                </tr>
+                <tr>
+                    <td>[% l('Exipration Month') %]</td>
+                    <td>
+                        <select name="expire_month">
+                            <option value="01">[% l("January") %]</option>
+                            <option value="02">[% l("February") %]</option>
+                            <option value="03">[% l("March") %]</option>
+                            <option value="04">[% l("April") %]</option>
+                            <option value="05">[% l("May") %]</option>
+                            <option value="06">[% l("June") %]</option>
+                            <option value="07">[% l("July") %]</option>
+                            <option value="08">[% l("August") %]</option>
+                            <option value="09">[% l("September") %]</option>
+                            <option value="10">[% l("October") %]</option>
+                            <option value="11">[% l("November") %]</option>
+                            <option value="12">[% l("December") %]</option>
+                        </select>
+                    </td>
+                </tr>
+                <tr>
+                    <td>[% l('Expiration Year') %]</td>
+                    <td>
+                        <select name="expire_year">
+                        [% year = date.format(date.now, '%Y');
+                        y = year;
+                        WHILE y < year + 10; # show ten years starting now %]
+                            <option value="[% y %]">[% y %]</option>
+                        [% y = y + 1; END %]
+                        </select>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan='2' align="center">
+                        <input type="submit" value="[% l('Submit Payment') %]" />
+                        <input type="reset" value="[% l('Cancel') %]"
+                            onclick="location.history.go(-1);" />
+                    </td>
+                </tr>
+                [% INCLUDE "default/opac/myopac/main_refund_policy.tt2" %]
+            </tbody>
+        </table>
+    </form>
+</div>
+[% END %]
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/main_payments.tt2 b/Open-ILS/web/templates/default/opac/myopac/main_payments.tt2
new file mode 100644 (file)
index 0000000..bf956b6
--- /dev/null
@@ -0,0 +1,45 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/main_base.tt2";
+    myopac_page = "main";
+    myopac_main_page = "payments";
+    limit = ctx.payment_history_limit;
+    offset = ctx.payment_history_offset;
+%]
+
+<div>
+    <div class="header_middle">
+        <span class="float-left">[% l('Payments History') %]</span>
+        <span class='float-left' style='padding-left: 10px;'>
+            <a href='main_payments?limit=[% limit %]&amp;offset=[% offset - limit %]'
+                [% IF offset == 0 %] class='invisible' [% END %]><span class="nav_arrow_fix">&#9668;</span>[% l('Previous') %]</a>
+            [%# TODO: get total to prevent paging off then end of the list.. %]
+            <a href='main_payments?limit=[% limit %]&amp;offset=[% offset + limit %]'
+               [% IF ctx.payments.size < limit %] class='invisible' [% END %] >[% l('Next') %]<span class="nav_arrow_fix">&#9658;</span></a>
+        </span>
+    </div>
+    <div class="clear-both"></div>
+
+    <table id='myopac_payments_table' width='100%' class='data_grid'>
+        <thead><tr>
+            <th>[% l('Payment Date') %]</th>
+            <th>[% l('Payment For') %]</th>
+            <th>[% l('Amount') %]</th>
+            <th>[% l('Receipt') %]</th> 
+        </tr></thead>
+        <tbody>
+            [% FOR payment IN ctx.payments %]
+            <tr>
+                <td>[% date.format(ctx.parse_datetime(payment.mp.payment_ts), DATE_FORMAT) %]</td>
+                <td>[% (payment.xact_type == 'grocery') ? payment.last_billing_type : payment.title %]</td>
+                <td>[% money(payment.mp.amount) %]</td>
+                <td>
+                    [%# post to print/email form... %]
+                    <a href=''>[% l('Print') %]</a> / <a href=''>[% l('Email') %]</a>
+                </td>
+            </tr>
+            [% END %]
+        </tbody>
+    </table>
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/main_refund_policy.tt2 b/Open-ILS/web/templates/default/opac/myopac/main_refund_policy.tt2
new file mode 100644 (file)
index 0000000..a1a81f9
--- /dev/null
@@ -0,0 +1,16 @@
+<tr>
+    <td colspan="3">
+        <br />
+        Important! You must have a printed receipt to be
+        eligible for a refund on lost items (regulations allow
+        for no exceptions).
+        <br />
+        <strong>
+            To ensure your necessary receipt information is
+            not lost, enter your email address above and a
+            receipt will be emailed to you. Otherwise, make
+            certain you have a printed receipt in hand before
+            closing the payment receipt screen.
+        </strong>
+    </td>
+</tr>
diff --git a/Open-ILS/web/templates/default/opac/myopac/prefs.tt2 b/Open-ILS/web/templates/default/opac/myopac/prefs.tt2
new file mode 100644 (file)
index 0000000..8ceeec3
--- /dev/null
@@ -0,0 +1,310 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/myopac/prefs_base.tt2";
+    myopac_page = "prefs";
+    prefs_page = 'personal' %]
+
+<div id="acct_info_main">
+    <div id='myopac.expired.alert'
+         class='hide_me'
+         style='margin-bottom: 20px;'>
+        <table class='data_grid'
+               width='100%'>
+            <tbody>
+                <tr>
+                    <td width='100%' class='red'>
+                        [% l("Your account expired on") %]
+                        <span id='myopac.expired.date'></span>!
+                        [% l("Please see a librarian to renew your account.") %]</td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+
+    <div id='myopac.notes.div'
+         class='hide_me'>
+        <table class='data_grid'
+               width='100%'>
+            <thead>
+                <tr>
+                    <td colspan='2'>
+                    <b>[% l("* Staff Notes *") %]</b></td>
+                </tr>
+            </thead>
+
+            <tbody id='myopac.notes.tbody'>
+                <tr id='myopac.notes.tr'>
+                    <td><b name='title'></b> : <span name=
+                    'value'></span></td>
+                </tr>
+            </tbody>
+        </table><br />
+    </div>
+
+    <table width='70%'
+           class='light_border data_grid'>
+        <tbody id='myopac_summary_tbody'>
+            <tr>
+                <td width='30%'
+                    class='color_4 light_border'>[% l("Name") %]</td>
+
+                <td class='light_border'>[% l(
+                    HUMAN_NAME_FORMAT,
+                    ctx.user.prefix, ctx.user.first_given_name,
+                    ctx.user.second_given_name, ctx.user.family_name,
+                    ctx.user.suffix
+                ) | html %]</td>
+
+                <td></td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>
+                [% l("Day Phone") %]</td>
+
+                <td class='light_border'
+                    id='myopac_summary_dayphone'>[% ctx.user.day_phone | html %]</td>
+
+                <td class='light_border'><a href='#'
+                   class="hide_me"
+                   id='myopac_summary_phone1_change'
+                   style=
+                   'text-decoration: underline;'>[% l("Change") %]</a></td>
+            </tr>
+
+            <tr id='myopac_update_phone1_row'
+                class='hide_me'>
+                <td class='myopac_update_cell'
+                    colspan='3'>
+                    <span class='myopac_update_span'>
+                        Enter New [% l("Day Phone") %]:
+                    </span>
+
+                    <input type='text' size='24' id='myopac_new_phone1' />
+                    <span class='myopac_update_span'>
+                        <button>
+                            <span class='myopac_update_span'>
+                                [% l("Submit") %]</span>
+                        </button>
+                    </span>
+                    <span class='myopac_update_span'>
+                        <button>
+                            <span class='myopac_update_span'>
+                                [% l("Cancel") %]</span>
+                        </button>
+                    </span>
+                </td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>
+                [% l("Evening Phone") %]</td>
+
+                <td class='light_border'
+                    id='myopac_summary_eveningphone'>[% ctx.user.evening_phone | html %]</td>
+
+                <td class='light_border'><a href='#'
+                   class="hide_me"
+                   id='myopac_summary_phone2_change'
+                   style=
+                   'text-decoration: underline;'>[% l("Change") %]</a></td>
+            </tr>
+
+            <tr id='myopac_update_phone2_row'
+                class='hide_me'>
+                <td class='myopac_update_cell'
+                    colspan='3'><span class='myopac_update_span'>New
+                    [% l("Evening Phone") %]:</span>
+                    <input type='text' size='24' id='myopac_new_phone2' />
+                    <span class='myopac_update_span'><button><span class=
+                        'myopac_update_span'>[% l("Submit") %]</span></button></span>
+                    <span class='myopac_update_span'><button><span class=
+                        'myopac_update_span'>[% l("Cancel") %]</span></button></span>
+                </td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>
+                [% l("Other Phone") %]</td>
+
+                <td class='light_border'
+                    id='myopac_summary_otherphone'>[% ctx.user.other_phone | html %]</td>
+
+                <td class='light_border'><a href='#'
+                   class="hide_me"
+                   id='myopac_summary_phone3_change'
+                   style=
+                   'text-decoration: underline;'>[% l("Change") %]</a></td>
+            </tr>
+
+            <tr id='myopac_update_phone3_row'
+                class='hide_me'>
+                <td class='myopac_update_cell'
+                    colspan='3'><span class='myopac_update_span'>Enter
+                    New [% l("Other Phone") %]:</span>
+                    <input type='text' size='24' id='myopac_new_phone3' />
+                    <span class='myopac_update_span'><button><span class=
+                        'myopac_update_span'>[% l("Submit") %]</span></button></span>
+                    <span class='myopac_update_span'><button><span class=
+                        'myopac_update_span'>[% l("Cancel") %]</span></button></span>
+                </td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>
+                    <div style="position:absolute">
+                        <div class="hide_me" style="position:relative;left:70px;top:-3px;">
+                            <a href="#"><img alt="Username Help" src="[% ctx.media_prefix %]/images/question-mark.png" /></a>
+                        </div>
+                    </div>[% l("Username") %]
+                </td>
+                <td class='light_border'>[% ctx.user.usrname | html %]</td>
+                <td class='light_border'><a href='update_username'>[% l("Change") %]</a></td>
+            </tr>
+            <tr>
+                <td class='color_4 light_border'>[% l("Password") %]</td>
+                <td class='light_border'>[% l("(not shown)") %]</td>
+                <td class='light_border'><a href='update_password'>[% l("Change") %]</a></td>
+            </tr>
+            <tr>
+                <td class='color_4 light_border'>[% l("Email Address") %]</td>
+                <td class='light_border'>[% ctx.user.email | html %]</td>
+                <td class='light_border'><a href='update_email'>[% l('Change') %]</a></td>
+            </tr>
+
+            [% IF ctx.user.ident_value %]<tr class="hide_me">
+                <td class='color_4 light_border'>
+                [% l("Primary Identification") %]</td>
+
+                <td class='light_border'>
+                    [%
+                    # l('[_1] ([_2])', ctx.user.ident_value, ctx.user.ident_type.name) | html
+                    # XXX uncomment the above line to show primary
+                    # identification. With a minor tweak it could
+                    # alternatively be shown but partially obscured. 
+                    %]
+                </td>
+                <td></td>
+            </tr>[% END %]
+
+            <tr>
+                <td class='color_4 light_border'>
+                [% l("Active Barcode") %]</td>
+
+                <td class='light_border'>[% ctx.user.card.barcode %]</td>
+
+                <td></td>
+            </tr>
+
+            <tr>
+                <td class='color_4 light_border'>
+                [% l("Home Library") %]</td>
+                <td class='light_border'>[% ctx.user.home_ou.name %]</td>
+                <td><a href='#'
+                   class="hide_me"
+                   style='text-decoration: underline;'>[% l("Change") %]</a></td>
+            </tr>
+            <tr class='hide_me'>
+                <td class='myopac_update_cell'
+                    colspan='3'>
+                    <span class='myopac_update_span'>
+                        New home library:</span>
+                    <select>
+                    </select>
+                    <span class='myopac_update_span'>
+                        <button>
+                            <span class= 'myopac_update_span'>
+                                [% l("Submit") %]</span>
+                        </button>
+                    </span>
+                    <span class='myopac_update_span'>
+                        <button>
+                            <span class= 'myopac_update_span'>
+                                [% l("Cancel") %]</span>
+                        </button>
+                    </span>
+                </td>
+            </tr>
+            <tr class="hide_me">
+                <td class='color_4 light_border'>
+                    [% l("Account Creation Date") %]
+                </td>
+                <td class='light_border'
+                    id='myopac_summary_create_date'></td>
+                <td></td>
+            </tr>
+        </tbody>
+    </table><br />
+    <hr class='opac-auto-013' color="#DCDBDB" />
+    <br />
+
+    <table width='100%' class='light_border data_grid'>
+        <thead>
+            <tr>
+                <td><strong>[% l("Addresses") %]</strong></td>
+
+            </tr>
+        </thead>
+        <tbody id='myopac_addr_tbody'>
+            [% FOR addr IN ctx.user.addresses %]
+            <tr class='[% addr.pending == "t" ? "pending-addr" : "light_border" %]'>
+                <td>
+                    <table>
+                        <tr>
+                            <td>[% l("Address Type") %]</td>
+                            <td name='myopac_addr_type'>[%
+                                IF addr.pending == "t";
+                                    "<strong>" _ l("*** PENDING ***") _ "</strong> ";
+                                END;
+                                addr.address_type | lower | ucfirst;
+                            %]</td>
+                        </tr>
+                        <tr>
+                            <td>[% l("Street") %]</td>
+                            <td name='myopac_addr_street'>[% addr.street1 | html %]</td>
+                        </tr>
+                        [% IF addr.street2 %]<tr>
+                            <td>[% l("Street") %]</td>
+                            <td name='myopac_addr_street2'>[% addr.street2 | html %]</td>
+                        </tr>[% END %]
+
+                        <tr>
+                            <td>[% l("City") %]</td>
+                            <td name='myopac_addr_city'>[% addr.city | html %]</td>
+                        </tr>
+
+                        <tr>
+                            <td>[% l("County") %]</td>
+                            <td name='myopac_addr_county'>[% addr.county| html  %]</td>
+                        </tr>
+
+                        <tr>
+                            <td>[% l("State") %]</td>
+                            <td name='myopac_addr_state'>[% addr.state | html %]</td>
+                        </tr>
+
+                        <tr>
+                            <td>[% l("Country") %]</td>
+                            <td name='myopac_addr_country'>[% addr.country | html %]</td>
+                        </tr>
+
+                        <tr>
+                            <td>[% l("Zip") %]</td>
+                            <td name='myopac_addr_zip'>[% addr.post_code | html %]</td>
+                        </tr>
+                        <tr>
+                            <td name='myopac_addr_edit_td'
+                                colspan='2' class='hide_me'>
+                                <a class='classic_link'
+                                    name='myopac_addr_edit_link'
+                                    href='#'>Edit Address</a>
+                            </td>
+                        </tr>
+                    </table>
+                </td>
+            </tr>
+            [% END %]
+        </tbody>
+    </table>
+</div>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/prefs_notify.tt2 b/Open-ILS/web/templates/default/opac/myopac/prefs_notify.tt2
new file mode 100644 (file)
index 0000000..14a824e
--- /dev/null
@@ -0,0 +1,128 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/myopac/prefs_base.tt2";
+    myopac_page = "prefs_notify";
+    prefs_page = 'notify' %]
+
+
+<form method='POST'>
+
+    <div style="float:right;width:65px;">
+        <input type='image' alt="[% l('Save') %]" src="[% ctx.media_prefix %]/images/save-btn.png" />
+    </div>
+
+    <table>
+        <thead><tr>
+            <th>[% l('Notifation Type') %]</th>
+            <th>[% l('Enabled') %]</th>
+        </tr></thead>
+        <tbody class='data_grid'>
+            [% IF optin.size == 0 %]
+                <strong>[% l('No notification preferences are configured') %]</strong>
+            [% END %]
+            [% FOR optin IN ctx.opt_in_settings %]
+                <tr>
+                    <td>[% optin.cust.label %]</td>
+                    <td>
+                        <input type='checkbox' name='setting' 
+                            value='[% optin.cust.name %]' 
+                            [% IF optin.value %] checked='checked' [% END %]/>
+                    </td>
+                </tr>
+            [% END %]
+        </tbody>
+    </table>
+</form>
+
+
+<!-- NOTIFICATION PREFS / leaving here for reference
+<table class="hide_me"
+       id="acct_notify_main">
+    <tbody>
+        <tr class="hide_me">
+            <td><span>[% l("Default Hold Notification Method") %]</span> <a class=
+            'classic_link'
+               href='#'>[% l("(Help)") %]</a></td>
+
+            <td style="padding-left:15px;"><select id=
+            'prefs_hold_notify'>
+                <option value='phone:email'
+                        selected='selected'>
+                    [% l("Use Phone and Email") %]
+                </option>
+
+                <option value='phone'>
+                    [% l("Use Phone Only") %]
+                </option>
+
+                <option value='email'>
+                    [% l("Use Email Only") %]
+                </option>
+            </select></td>
+        </tr>
+
+        <tr>
+            <td style="padding-top:10px;"><strong>Pick Up Notice for
+            Holds</strong><br />
+            <input type="checkbox"
+                   id="opac.hold_notify.email"
+                   name="opac.hold_notify.email" /> <label for=
+                   "opac.hold_notify.email">Email</label><br />
+            <input type="checkbox"
+                   id="opac.hold_notify.phone"
+                   name="opac.hold_notify.phone" /> <label for=
+                   "opac.hold_notify.phone">Phone</label>
+                   <b>(Temporarily phone notification will generate a
+                   mailed paper notice.)</b></td>
+        </tr>
+
+        <tr>
+            <td style="padding-top:10px;"><strong>Expire Notice for
+            Holds</strong><br />
+            <input type="checkbox"
+                   id="notification.hold.expire.email"
+                   name="notification.hold.expire.email" /> <label for=
+                   "notification.hold.expire.email">Email</label></td>
+        </tr>
+
+        <tr>
+            <td style="padding-top:10px;"><strong>Cancel Notice for
+            Holds</strong><br />
+            <input type="checkbox"
+                   id="notification.hold.cancel.email"
+                   name="notification.hold.cancel.email" /> <label for=
+                   "notification.hold.cancel.email">Email</label></td>
+        </tr>
+
+        <tr>
+            <td style="padding-top:10px;"><strong>Overdue First
+            Notice</strong><br />
+            <input type="checkbox"
+                   id="notification.overdue.first.email"
+                   name="notification.overdue.first.email" />
+                   <label for=
+                   "notification.overdue.first.email">Email</label><br />
+            <input type="checkbox"
+                   id="notification.overdue.first.phone"
+                   name="notification.overdue.first.phone" />
+                   <label for=
+                   "notification.overdue.first.phone">Phone</label>
+                   <b>(Temporarily phone notification will generate a
+                   mailed paper notice.)</b></td>
+        </tr>
+
+        <tr>
+            <td style="padding-top:10px;"><strong>Courtesy
+            Notice</strong><br />
+            <input type="checkbox"
+                   id="notification.predue.email"
+                   name="notification.predue.email" /> <label for=
+                   "notification.predue.email">Email</label><br /></td>
+        </tr>
+    </tbody>
+</table>
+-->
+
+
+[% END %]
+
+
diff --git a/Open-ILS/web/templates/default/opac/myopac/prefs_settings.tt2 b/Open-ILS/web/templates/default/opac/myopac/prefs_settings.tt2
new file mode 100644 (file)
index 0000000..daf65be
--- /dev/null
@@ -0,0 +1,114 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/myopac/prefs_base.tt2";
+    myopac_page = "prefs_notify";
+    prefs_page = 'settings' %]
+
+USER SETTINGS
+
+        <!-- SEARCH PREFS SAVE, MOVE TO SUB-TEMPLATE
+        <div style="float:right;width:65px;">
+            <div style="position:absolute">
+                <div style="position:relative;top:75px;">
+                    <a id='acct_prefs_save'
+                         class='hide_me'
+                         href="#"><img alt="Save"
+                         src="[% ctx.media_prefix %]/images/save-btn.png" /></a>
+                </div>
+            </div>
+        </div>
+        -->
+
+
+        <!-- SEARCH PREFERENCES / leaving here for reference
+        <table class="hide_me full-width" id="acct_search_main">
+            <tbody id='myopac_prefs_tbody'>
+                <tr id='myopac_prefs_loading'>
+                    <td colspan='3'><b>[% l("Loading...") %]</b></td>
+                </tr>
+
+                <tr id='myopac_prefs_row'>
+                    <td width='20%'>[% l("Search hits per page") %]</td>
+
+                    <td>
+                        <div style="position:absolute">
+                            <div style="position:relative;top:0px;left:55px;">
+                                <a href="#">
+                                <img alt="Search Hits Help"
+                                     src="[% ctx.media_prefix %]/images/question-mark.png" /></a>
+                            </div>
+                        </div><select id='prefs_hits_per'
+                            style="position:relative;z-index:100;">
+                            <option value='5'>
+                                5
+                            </option>
+
+                            <option value='8'>
+                                8
+                            </option>
+
+                            <option value='10'>
+                                10
+                            </option>
+
+                            <option value='15'>
+                                15
+                            </option>
+
+                            <option value='20'>
+                                20
+                            </option>
+
+                            <option value='25'>
+                                25
+                            </option>
+
+                            <option value='50'>
+                                50
+                            </option>
+                        </select>
+                    </td>
+                </tr>
+
+                <tr>
+                    <td colspan="2"><label for="circHistStart">Keep history of
+                    checked out items?</label> <input type="checkbox"
+                           id="circHistStart" /></td>
+                </tr>
+
+                <tr class="hide_me">
+                    <td>[% l("Default Font Size") %]</td>
+
+                    <td><select id='prefs_def_font'>
+                        <option value='regular'>
+                            [% l("Regular Font") %]
+                        </option>
+
+                        <option value='large'>
+                            [% l("Large Font") %]
+                        </option>
+                    </select></td>
+                </tr>
+
+                <tr class="hide_me">
+                    <td>[% l("Default Search Location") %]</td>
+                    <td>
+                        <div style='margin-bottom: 5px;'>
+                            <input type='checkbox' id='myopac_pref_home_lib' />
+                                 [% l("Always search my home library by default.") %]
+                        </div>
+                        <select id='prefs_def_location'></select>
+                    </td>
+                </tr>
+
+                <tr class="hide_me">
+                    <td>[% l("Default Search Range") %]</td>
+
+                    <td><select id='prefs_def_range'>
+                        </select></td>
+                </tr>
+            </tbody>
+        </table>
+        [% INCLUDE "default/opac/parts/myopac/prefs_hints.tt2" %]
+        -->
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/update_email.tt2 b/Open-ILS/web/templates/default/opac/myopac/update_email.tt2
new file mode 100644 (file)
index 0000000..2261c29
--- /dev/null
@@ -0,0 +1,23 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+    myopac_page = "prefs"  %]
+<div id='myopac_summary_div' style="padding:0px;">
+
+[% IF ctx.invalid_email %]
+    <div id='account-update-email-error'>
+        [% | l(ctx.invalid_email) %]
+        The email address "<b>[_1]</b>" is invalid.  Please try a different email address.
+        [% END %]
+    </div>
+[% END %]
+
+<form method='POST' id='account-update-email'>
+    <table> 
+        <tr><td>[% l('Current Email') %]</td><td>[% ctx.user.email | html %]</td></tr>
+        <tr><td>[% l('New Email') %]</td><td><input type='text' name='email' value='[% ctx.invalid_email | html %]'/></td></tr>
+        <tr><td colspan='2' align='center'><input type='submit'/></td></tr>
+    </table>
+</form>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/update_password.tt2 b/Open-ILS/web/templates/default/opac/myopac/update_password.tt2
new file mode 100644 (file)
index 0000000..d248cdf
--- /dev/null
@@ -0,0 +1,33 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+    myopac_page = "prefs"  %]
+
+<div id='myopac_summary_div' style="padding:0px;">
+
+[% IF ctx.password_invalid %]
+    <div id='account-update-email-error'> <!-- borrow css from update-email page -->
+        [% |l %] New password is invalid.  Please try a different password.  [% END %]
+    </div>
+
+[% ELSIF ctx.password_nomatch %]
+    <div id='account-update-email-error'>
+        [% |l %] Passwords do not match. [% END %]
+    </div>
+
+[% ELSIF ctx.password_incorrect %]
+    <div id='account-update-email-error'>
+        [% |l %] Your current password was not correct. [% END %]
+    </div>
+[% END %]
+
+<form method='POST' id='account-update-email'> 
+    <table> 
+        <tr><td>[% l('Current Password') %]</td><td><input type='password' name='current_pw'/></td></tr>
+        <tr><td>[% l('New Password') %]</td><td><input type='password' name='new_pw'/></td></tr>
+        <tr><td>[% l('New Password Again') %]</td><td><input type='password' name='new_pw2'/></td></tr>
+        <tr><td colspan='2' align='center'><input type='submit'/></td></tr>
+    </table>
+</form>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/myopac/update_username.tt2 b/Open-ILS/web/templates/default/opac/myopac/update_username.tt2
new file mode 100644 (file)
index 0000000..1294917
--- /dev/null
@@ -0,0 +1,30 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+    myopac_page = "prefs"  %]
+<div id='myopac_summary_div' style="padding:0px;">
+
+[% IF ctx.invalid_username %]
+    <div id='account-update-email-error'> <!-- borrow css from update-email page -->
+        [% | l(ctx.invalid_username) %]
+        "<b>[_1]</b>" is not a valid username.  Usernames cannot have any spaces.  Please try a different username.
+        [% END %]
+    </div>
+
+[% ELSIF ctx.username_exists %]
+    <div id='account-update-email-error'>
+        [% | l(ctx.username_exists) %]
+        The username "<b>[_1]</b>" is taken.  Please try a different username.
+        [% END %]
+    </div>
+[% END %]
+
+<form method='POST' id='account-update-email'> 
+    <table> 
+        <tr><td>[% l('Current Username') %]</td><td>[% ctx.user.usrname | html %]</td></tr>
+        <tr><td>[% l('New Username') %]</td><td><input type='text' name='username' value='[% ctx.invalid_username | html %]'/></td></tr>
+        <tr><td colspan='2' align='center'><input type='submit'/></td></tr>
+    </table>
+</form>
+
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/parts/advanced/global_row.tt2 b/Open-ILS/web/templates/default/opac/parts/advanced/global_row.tt2
new file mode 100644 (file)
index 0000000..ae8081e
--- /dev/null
@@ -0,0 +1,33 @@
+[%
+    contains_options = [
+        {value => 'contains', label => l('Contains')},
+        {value => 'nocontains', label => l('Does not contain')},
+        {value => 'phrase', label => l('Contains phrase')},
+        {value => 'exact', label => l('Matches exactly')}
+    ];
+    contains = CGI.param('contains');
+    queries = CGI.param('query');
+    qtypes = CGI.param('qtype') || ['keyword' x 3];
+    FOR qtype IN qtypes;
+        c = contains.shift;
+        q = queries.shift; %]
+<tr[% IF loop.first %] id="adv_global_row"[% END %]>
+    <td align='left' width='100%' nowrap='nowrap'>
+        <span class="opac-auto-078">
+            [% INCLUDE "default/opac/parts/qtype_selector.tt2"
+                query_type=qtype %]
+        </span>
+        <select name='contains' style='margin-right: 7px;'>
+            [% FOR o IN contains_options;
+                |l(o.value, o.label) -%]
+            <option value="[_1]"[% c == o.value ? ' selected="selected"' : '' %]>[_2]</option>
+            [% END; END %]
+        </select>
+        <input type='text' size='18' name='query' value="[% q | html %]" />
+        <a href="javascript:;" class="row-remover"
+            title="[% l('Remove row') %]" alt="[% l('Remove row') %]"
+            onclick='var row = this.parentNode.parentNode;var tbody = row.parentNode; if( tbody.getElementsByTagName("tr").length > 2 ) row.parentNode.removeChild(row);'><img src="[% ctx.media_prefix %]/images/adv_row_close_btn.png" /></a>
+    </td>
+</tr>
+[%      i = i + 1;
+    END %]
diff --git a/Open-ILS/web/templates/default/opac/parts/advanced/search.tt2 b/Open-ILS/web/templates/default/opac/parts/advanced/search.tt2
new file mode 100644 (file)
index 0000000..9f1c949
--- /dev/null
@@ -0,0 +1,204 @@
+<form id="adv_search_form" action="[% ctx.opac_root %]/results" method="GET">
+<table id='adv_global_search' class='data_grid data_grid_center' width='100%'>
+    <tr style='border-bottom: none;'>
+        <!-- Contains the user-addable(?) rows to define search class, containment and text -->
+        <td valign='top' class='opac-auto-012'>
+            <table width='100%' id='adv_global_input_table'>
+                <thead>
+                    <tr>
+                        <td>
+                            <div style="width:100%;" class="header_middle">
+                                [% l("Search Input") %]
+                            </div>
+                        </td>
+                    </tr>
+                </thead>
+                <tbody id='adv_global_tbody'>
+                    [% INCLUDE "default/opac/parts/advanced/global_row.tt2" %]
+                    <!-- add a new row -->
+                    <tr id='adv_global_addrow'>
+                        <td align='left' style="padding-top:7px;">
+                            <a href="javascript:;" id="myopac_new_global_row" onclick='addSearchRow();'>Add Search Row</a>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td align='top'>
+          <div style="width:100%;" class="header_middle">Search Filters</div>
+          <table cellpadding='10' cellspacing='0' border='0'><tr>
+            <td valign='top'>
+                <strong>[% l("Item Type") %]</strong><br />
+                [%  INCLUDE "default/opac/parts/coded_value_selector.tt2"
+                        attr="mattype" multiple="multiple" size="4"
+                        id="adv_global_item_type_basic" %]
+            </td>
+            <td valign='top'>
+                <strong>[% l("Language") %]</strong><br />
+                [%  INCLUDE "default/opac/parts/coded_value_selector.tt2"
+                        attr="item_lang" multiple="multiple" size="4" %]
+            </td>
+            <td valign='top'>
+                <strong>[% l("Audience") %]</strong><br />
+                    [% INCLUDE "default/opac/parts/coded_value_selector.tt2"
+                        attr="audience" id="adv_global_audience_basic" 
+                        multiple="multiple" size="4" %]
+                </select>
+                    <!--<a id='adv_global_audience_link_adv' class='classic_link adv_adv_link'
+                        href='javascript:void(0);' onclick='
+                        hideMe($("adv_global_audience_basic"));
+                        unHideMe($("adv_global_audience"));
+                        hideMe(this);
+                        unHideMe($("adv_global_audience_link_basic"));
+                        '>[% l("Advanced") %]</a>
+                    <a id='adv_global_audience_link_basic' class='hide_me classic_link adv_adv_link'
+                        href='javascript:void(0);' onclick='
+                        unHideMe($("adv_global_audience_basic"));
+                        hideMe($("adv_global_audience"));
+                        unHideMe($("adv_global_audience_link_adv"));
+                        hideMe(this);'>[% l("Basic") %]</a>-->
+            </td>
+            <td valign='top'>
+            <strong>[% l("Sort Results") %]</strong>
+              <table class='opac-auto-017'>
+                <tr>
+                    <td align='center' width='100%'>
+                        [% INCLUDE "default/opac/parts/filtersort.tt2"
+                            value=CGI.param('sort') %]
+                    </td>
+                </tr>
+              </table>
+            </td>
+          </tr></table>
+        </td>
+    </tr>
+    <tr>
+        <td colspan="2">
+            <table cellpadding='10' cellspacing='0' border='0'>
+                <tbody>
+                    <tr>
+                        <td valign='top'>
+                            <strong>[% l("Search Library") %]</strong><br />
+                            [% PROCESS "default/opac/parts/org_selector.tt2";
+                                PROCESS build_org_selector name='loc' value=loc %]
+                            <div style="position:relative;top:7px;">
+                                <input type='checkbox' name="modifier"
+                                value="available"[% CGI.param('modifier').grep('available').size ? ' checked="checked"' : '' %]
+                                    id='opac.result.limit2avail' />
+                                <label style="position:relative;top:-2px;"
+                                    for='opac.result.limit2avail'>
+                                    [% l("Limit to Available") %]</label>
+                            </div>
+                        </td>
+                        <td valign='top'>
+                            <strong>[% l("Publication Year") %]</strong><br />
+                            <select id='adv_global_pub_date_type' name='pubdate' onchange='
+                                if(this.selectedIndex == 3)
+                                    unHideMe($("adv_global_pub_date_2_span"));
+                                else
+                                    hideMe($("adv_global_pub_date_2_span"));'>
+                                    [%  FOR opt IN [
+                                            {"code" => "is", "label" => l("Is")},
+                                            {"code" => "before", "label" => l("Before")},
+                                            {"code" => "after", "label" => l("After")},
+                                            {"code" => "between", "label" => l("Between")}
+                                        ];
+                                            |l(opt.code, opt.label) %]
+                                        <option value="[_1]"[% CGI.param('pubdate') == opt.code ? ' selected="selected"' : '' %]>[_2]</option>
+                                    [%  END; END %]
+                            </select>    
+                            <div style='margin-top:5px;'>
+                                <input id='adv_global_pub_date_1' name='date1' type='text' size='4' maxlength='4' value="[% CGI.param('date1') | html %]" />
+                                <span id='adv_global_pub_date_2_span' class='[% CGI.param("pubdate") == "between" ? "" : "hide_me" %]'>
+                                   [% l("and") %] <input name='date2' id='adv_global_pub_date_2' type='text' size='4' maxlength='4' value="[% CGI.param('date2') | html %]" />
+                                </span>
+                            </div>
+                        </td>
+                    </tr>
+                    <!-- copy location selector -->
+                    <tr id='adv_copy_location_filter_row' class='hide_me'>
+                        <td align='right'>[% l("Shelving Location") %]</td>
+                        <td align='left' id='adv_copy_location_filter_td'>
+                            <select size='3' id='adv_copy_location_filter_select' multiple='multiple'>
+                            </select>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr class='border_4_2'>
+        <td align="left" colspan='2'>
+            <input type="image" src="[% ctx.media_prefix %]/images/search_btn.gif"
+            alt="[% l('Search') %]" class='pointer' />
+            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+            <a href="javascript:document.getElementById('adv_search_form').reset();"
+                id="adv_reset">[% l('Reset Form') %]</a>
+        </td>
+    </tr>
+</table>
+<input type="hidden" name="_adv" value="1" />
+</form>
+<div id='adv_quick_search_sidebar' class='sidebar_chunk hide_me'> 
+    <div id='adv_quick_search'>
+        <div class='adv_quick_search color_4'><b>[% l("Quick Search") %]</b></div>
+        <div style='margin-top: 8px;'>
+            <table><tbody><tr>
+                <td>
+                    <select id='adv_quick_type'>
+                        <option value='isbn'>[% l("ISBN") %]</option>
+                        <option value='issn'>[% l("ISSN") %]</option>
+                        <option value='cn'>[% l("Call Number") %]</option>
+                        <option value='lccn'>[% l("LCCN") %]</option>
+                        <option value='tcn'>[% l("TCN") %]</option>
+                        <option value='barcode'>[% l("Item Barcode") %]</option>
+                    </select>
+                </td><td>
+                    <input type='text' id='adv_quick_text' size='16' />
+                </td>
+            </tr></tbody></table>
+        </div>
+
+        <div style='margin-top: 8px;' class='adv_quick_search_submit'>
+            <!-- XXX TODO make a real form, and make a real submitter (quick
+            submit, FKA advGenericSearch() -->
+            <img src="[% ctx.media_prefix %]/images/search_btn.gif"
+                alt="[% l('Search') %]" id="adv_quick_submit" class='pointer' />
+        </div>
+    </div>
+</div>
+
+
+<div id='adv_marc_search_sidebar' class='sidebar_chunk hide_me'
+    style='width:400px; margin-top: 20px;'> 
+    <div class='adv_quick_search color_4'><b>[% l("MARC Expert Search") %]</b></div>
+    <table style='margin: 3px; width: 100%;' id='adv_sdbar_table'
+        class='border_4_3'>
+        <tbody>
+            <tr>
+                <td align="right">[% l("Tag:") %]</td>
+                <td align="left"><input name='advanced.marc.tag' maxlength='3' size='3' /></td>
+                <td align="right">[% l("Subfield:") %]</td>
+                <td align="left"><input name='advanced.marc.subfield' maxlength='1' size='1' /></td>
+            </tr>
+            <tr>
+                <td align="right">[% l("Value:") %]</td>
+                <td colspan='3' align="left"><input name='advanced.marc.value' size='18' /></td>
+            </tr>
+            <tr name='crow' class='hide_me'>
+                <td colspan='4' align='center'>
+                    <a href='javascript:void(0);' class='classic_link'>[% l("close") %]</a>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+    <div id='adv_marc_submit' class='adv_quick_search_submit'>
+        <a style='margin-right: 4px; position:relative;top:-10px;'
+            class='classic_link' href='javascript:advAddMARC();'>[% l("Add Row") %]</a>
+        <!-- XXX TODO make a real form, and make a real submitter (FKA
+        advMARCRun()) -->
+        <img alt="Search" src="[% ctx.media_prefix %]/images/search_btn.gif" class='pointer' />
+    </div>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/anon_list.tt2 b/Open-ILS/web/templates/default/opac/parts/anon_list.tt2
new file mode 100644 (file)
index 0000000..19a7440
--- /dev/null
@@ -0,0 +1,65 @@
+        [% IF ctx.mylist.size %]
+        <form action="[% ctx.opac_root %]/mylist/move" method="POST">
+        <div id='acct_list_template2'>
+            <div style="width:100%">
+                <table cellpadding="0" cellspacing="0" border="0">
+                    <tr>
+                        <td id='anon_list_name'>
+                            [% l('Temporary List') %]
+                        </td>
+                        <td>
+                            <!-- <a href="#"><img
+                                alt="[% l('Anonymous List Help') %]"
+                                src="[% ctx.media_prefix %]/images/question-mark.png" /></a>-->
+                        </td>
+                    </tr>
+                </table>
+                <div class="float-right"></div>
+                <div class="clear-both pad-bottom-five"></div>
+            </div>
+            <table cellpadding='0' cellspacing='0' border='0'>
+                <thead id="acct_list_header_anon">
+                    <tr>
+                        <td width="1%" style="padding-left:10px;">
+                            <input type="checkbox" onclick="
+                                var inputs=document.getElementsByTagName('input'); 
+                                for (i = 0; i < inputs.length; i++) { 
+                                    if (inputs[i].name == 'record' && !inputs[i].disabled) inputs[i].checked = this.checked;}"/>
+                        </td>
+                        <td width="49%" style="padding-left:5px;">[% l('Title') %]</td>
+                        <td width="49%" style="padding-left:5px;">[% l('Author(s)') %]</td>
+                        <td width="1%" class="nowrap">
+                            <select class="opac-auto-179" name="action">
+                                <option>[% l('-- Actions for this list --') %]</option>
+                                <!-- XXX not ready <option value="hold">[% l('Place Hold') %]</option> -->
+                                <option value="delete">[% l('Remove Items') %]</option>
+                                [% IF ctx.user AND ctx.bookbags.size %]
+                                <optgroup label="Move selected items to">
+                                    [% FOR bbag IN ctx.bookbags %]]
+                                    <option value="[% bbag.id %]" class="opac-auto-179-inner-option">[% bbag.name %]</option>
+                                    [% END %]
+                                </optgroup>
+                                [% END %]
+                            </select>
+                            <input type="submit" value="[% l('Go') %]" />
+                        </td>
+                    </tr>
+                </thead>
+                <tbody id='anon_list_tbody'>
+                    [% FOR item IN ctx.mylist;
+                        attrs = {marc_xml => ctx.mylist_marc_xml.$item};
+                        PROCESS get_marc_attrs args=attrs %]
+                    <tr>
+                        <td class="opac-auto-097b" style="padding-left: 10px;">
+                            <input type="checkbox" name="record" value="[% item %]" />
+                        </td>
+                        <td class="opac-auto-097b" style="padding-left: 5px;">[% attrs.title %]</td>
+                        <td class="opac-auto-097b" style="padding-left: 5px;">[% attrs.author %]</td>
+                    </tr>
+                    [% END %]
+                </tbody>
+            </table>
+            <br /><br />
+        </div>
+        </form>
+        [% END %]
diff --git a/Open-ILS/web/templates/default/opac/parts/base.tt2 b/Open-ILS/web/templates/default/opac/parts/base.tt2
new file mode 100644 (file)
index 0000000..d54a7e0
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns='http://www.w3.org/1999/xhtml' lang='[% ctx.locale %]' xml:lang='[% ctx.locale %]'>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+        [% IF ctx.authtime %]
+        <meta http-equiv="refresh" content="[% ctx.authtime %];[% ctx.logout_page %]">
+        [% END %]
+        <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/default/opac/semiauto.css" />
+        <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/default/opac/style.css" />
+        <title>[% l('Catalog - [_1]', ctx.page_title) %]</title>
+        <link rel="unapi-server" type="application/xml" title="unAPI" href="/opac/extras/unapi" />
+    </head>
+    <body>
+        [% content %] 
+        [% INCLUDE 'default/opac/parts/footer.tt2' %]
+        [% INCLUDE 'default/opac/parts/js.tt2' %]
+    </body>
+</html>
diff --git a/Open-ILS/web/templates/default/opac/parts/cn_browse.tt2 b/Open-ILS/web/templates/default/opac/parts/cn_browse.tt2
new file mode 100644 (file)
index 0000000..282bfd9
--- /dev/null
@@ -0,0 +1,44 @@
+<!-- ****************** cn_browse.xml ***************************** -->
+<div id='cn_browse' class='cn_browser'>
+    <div id='cn_browse_loading' class='cn_browse_loading hide_me'>
+        [% l("Loading Callnumber Page...") %]
+    </div>
+    <div id='cn_browse_div'> 
+        <div class='color_4'>
+            <span>[% l("You are now browsing") %]</span>
+            <b id='cn_browse_where'> </b>
+        </div>
+        <table class='data_grid bookshelf' width='100%'>
+            <thead>
+                <tr>
+                    <td>
+                        <a id='cn_browse_next' class='classic_link' 
+                        href='javascript:cnBrowsePrev();'><b>[% l("&lt;&lt; Previous Page") %]</b></a>
+                    </td>
+                    <td colspan='1' align='center'>[% l("Shelf Browser") %]</td>
+                    <td>
+                        <a id='cn_browse_prev' class='classic_link' 
+                            href='javascript:cnBrowseNext();'><b>[% l("Next Page &gt;&gt;") %]</b></a>
+                    </td>
+                </tr>
+            </thead>
+            <tbody id='cn_tbody'>
+                <tr id='cn_browse_row'>
+                    <td id='cn_browse_td' class='cn_browse_item' width='25%' valign='top'>
+                        <a><img height='60' width='50' 
+                            class='cn_browse_info' name='cn_browse_pic' border='0' /></a>
+                        <div class='cn_browse_info bold' name='cn_browse_cn'></div>
+                        <div class='cn_browse_info'>
+                            <a name='cn_browse_title' class='classic_link'></a>
+                        </div>
+                        <div class='cn_browse_info'>
+                            <a name='cn_browse_author' class='classic_link'>  </a>
+                        </div>
+                        <div class='cn_browse_info' name='cn_browse_lib'>  </div>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
+<!-- ****************** end: cn_browse.xml ***************************** -->
diff --git a/Open-ILS/web/templates/default/opac/parts/coded_value_selector.tt2 b/Open-ILS/web/templates/default/opac/parts/coded_value_selector.tt2
new file mode 100644 (file)
index 0000000..cfcd9a0
--- /dev/null
@@ -0,0 +1,15 @@
+[%- name = name || "fi:" _ attr;
+    id = id || attr _ "_selector";
+    values = values || CGI.param(name); -%]
+<select id='[% id %]' name='[% name %]'[%
+    multiple ? ' multiple="multiple"' : '';
+    size ? (' size="' _ size _ '"') : ''; %]>
+[%  all_values = ctx.search_ccvm('ctype', attr);
+IF none_ok %]
+    <option value=''>[% l('-- Any --') %]</option>
+[% END;
+FOR o IN all_values;
+   |l(o.value) %]
+    <option value='[% o.code %]'[% values.grep('^' _ o.code _ '$').size ? ' selected="selected"' : '' %]>[_1]</option>
+[%  END; END -%]
+</select>
diff --git a/Open-ILS/web/templates/default/opac/parts/filtersort.tt2 b/Open-ILS/web/templates/default/opac/parts/filtersort.tt2
new file mode 100644 (file)
index 0000000..795b179
--- /dev/null
@@ -0,0 +1,15 @@
+<select class="results_header_sel" id='opac.result.sort' name="sort">
+    <option value=''>[% l("Sort by Relevance") %]</option>
+    <optgroup label='[% l("Sort by Title") %]'>
+        <option value='title'[% value == 'title' ? ' selected="selected"' : '' %]>[% l("Title: A to Z") %]</option>
+        <option value='title.desc'[% value == 'title.desc' ? ' selected="selected"' : '' %]>[% l("Title: Z to A") %]</option>
+    </optgroup>
+    <optgroup label='[% l("Sort by Author") %]'>
+        <option value='author'[% value == 'author' ? ' selected="selected"' : '' %]>[% l("Author: A to Z") %]</option>
+        <option value='author.desc'[% value == 'author.desc' ? ' selected="selected"' : '' %]>[% l("Author: Z to A") %]</option>
+    </optgroup>
+    <optgroup label='[% l("Sort by Publication Date") %]'>
+        <option value='pubdate.desc'[% value == 'pubdate.desc' ? ' selected="selected"' : '' %]>[% l("Date: Newest to Oldest") %]</option>
+        <option value='pubdate'[% value == 'pubdate' ? ' selected="selected"' : '' %]>[% l("Date: Oldest to Newest") %]</option>
+    </optgroup>
+</select>
diff --git a/Open-ILS/web/templates/default/opac/parts/footer.tt2 b/Open-ILS/web/templates/default/opac/parts/footer.tt2
new file mode 100644 (file)
index 0000000..eb6db18
--- /dev/null
@@ -0,0 +1,21 @@
+<div id="footer">
+    <a href="http://example.com">[% l('Bottom Link 1') %]</a> &nbsp;|&nbsp;
+    <a href="http://example.com">[% l('Bottom Link 2') %]</a> &nbsp;|&nbsp;
+    <a href="http://example.com">[% l('Bottom Link 3') %]</a> &nbsp;|&nbsp;
+    <a href="http://example.com">[% l('Bottom Link 4') %]</a> &nbsp;|&nbsp;
+    <a href="http://example.com">[% l('Bottom Link 5') %]</a>
+
+    <div id="copyright_text" style="margin-top: 2em;">
+        [% l('Copyright &copy; 2006-[_1] Georgia Public Library Service, and others', date.format(date.now, '%Y')) %]
+    </div>
+    <div id="footer_logo">
+        [% l('Powered by') %]
+        <a href="http://evergreen-ils.org">
+            <img src="[% ctx.media_prefix %]/opac/images/eg_tiny_logo.jpg"
+                style="border:none; width: 94px; height: 16px;"
+                alt="[% l('Evergreen') %]"
+            />
+        </a>
+    </div>
+</div>
+
diff --git a/Open-ILS/web/templates/default/opac/parts/header.tt2 b/Open-ILS/web/templates/default/opac/parts/header.tt2
new file mode 100644 (file)
index 0000000..114b4c3
--- /dev/null
@@ -0,0 +1,55 @@
+[%- USE money = format(l('$%.2f'));
+    USE date;
+    USE CGI = CGI_utf8;
+    USE EGI18N;
+    USE POSIX;
+    SET DATE_FORMAT = l('%m/%d/%Y');
+
+    # Don't wrap in l() here; do that where this format string is actually used.
+    SET HUMAN_NAME_FORMAT = '[_1] [_2] [_3] [_4] [_5]';
+
+    # x and y are artifacts of using <input type="image" /> tags instead of
+    # true submit buttons, and their values are never used. page is used, but
+    # currently none of the use cases for rendering the query_string back
+    # into page output call for propagating the value of the page variable.
+
+    query_string = CGI.query_string |
+        replace(';x=\d+','') | replace(';y=\d+','') | replace(';page=\d*', '') |
+        replace(';', '&') | replace('&', '&amp;');
+
+    propagator = '?' _ query_string;
+
+    is_advanced = CGI.param("_adv").size;
+%]
+
+
+[%# XXX KCLS Note... Remove me soon...
+BEGIN;
+INSERT INTO config.record_attr_definition (name, label, tag, sf_list)
+    VALUES ('mattype', 'Material Type', '998', 'd');
+INSERT INTO config.coded_value_map (ctype, code, value)
+    VALUES
+        ('mattype', 'a', 'Book'),
+        ('mattype', 'i', 'Book on cassette'),
+        ('mattype', 'n', 'Book on CD'),
+        ('mattype', 'x', 'Download music'),
+        ('mattype', 'y', 'Download video'),
+        ('mattype', 'h', 'DVD'),
+        ('mattype', 'w', 'eBook - Audio'),
+        ('mattype', 'v', 'eBook - Text'),
+        ('mattype', 'e', 'Equipment'),
+        ('mattype', 'f', 'Films'),
+        ('mattype', 'o', 'Kit'),
+        ('mattype', 'q', 'Large print'),
+        ('mattype', 'b', 'Magazine'),
+        ('mattype', 'd', 'Microform'),
+        ('mattype', 'k', 'Music cassette'),                                                                                                                                                              ('mattype', 'j', 'Music CD'),
+        ('mattype', 'l', 'Music LP'),                                                                                                                                                                    ('mattype', 'p', 'Newspaper'),
+        ('mattype', 't', 'Online'),                                                                                                                                                                      ('mattype', 'u', 'Player'),
+        ('mattype', 'c', 'Printed music / scores'),                                                                                                                                                      ('mattype', '2', 'Read along with cassette'),
+        ('mattype', '5', 'Read along with CD'),                                                                                                                                                          ('mattype', 'm', 'Software'),
+        ('mattype', 'g', 'Video'),                                                                                                                                                                       ('mattype', 'r', '3-D Object'),
+        ('mattype', 'z', 'Map'),                                                                                                                                                                         ('mattype', 's', 'Slide set');
+COMMIT;
+%]
+
diff --git a/Open-ILS/web/templates/default/opac/parts/homesearch.tt2 b/Open-ILS/web/templates/default/opac/parts/homesearch.tt2
new file mode 100644 (file)
index 0000000..e5104b6
--- /dev/null
@@ -0,0 +1,3 @@
+<div style='width:664px;height:35px;background:#FFFFFF;'>
+    <strong><center><img src="[% ctx.media_prefix %]/opac/images/main_logo.jpg" /></center></strong>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/js.tt2 b/Open-ILS/web/templates/default/opac/parts/js.tt2
new file mode 100644 (file)
index 0000000..4f7771d
--- /dev/null
@@ -0,0 +1,24 @@
+<!-- JS imports, etc.  -->
+
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/opac/simple.js"></script>
+
+[% IF ctx.is_staff %]
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/opac/staff.js"></script>
+[% END %]
+
+<!-- Google Analytics -->
+<script type="text/javascript">
+/* uncomment when ready */ /*
+  var _gaq = _gaq || [];
+  _gaq.push(['_setAccount', 'UA-3018520-10']);
+  _gaq.push(['_trackPageview']);
+
+  (function() {
+    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+  })();
+*/
+</script>
+<!-- End Google Analytics -->
+
diff --git a/Open-ILS/web/templates/default/opac/parts/login/form.tt2 b/Open-ILS/web/templates/default/opac/parts/login/form.tt2
new file mode 100644 (file)
index 0000000..b30d47f
--- /dev/null
@@ -0,0 +1,156 @@
+<!-- TODO: MOVE INTO SEPARATE FORGOT-PASSWORD PAGE 
+
+<div class="hide_me">
+       <div class='login_text color_1' style='padding: 4px; text-align: center;'>
+               <span>[% l("Login") %]</span>
+       </div>
+       <br/>
+</div>
+<div class="hide_me" id="forget_pw">
+    <h1>Password Reset</h1>
+       Username or Barcode<br />
+       <input type="text" id="forget_pw_user" /><br /><br />
+       Email Address on account<br />
+       <input type="text" id="forget_pw_email" /><br />
+    <a href="#">Submit</a> &nbsp;
+    <a href="#">Cancel</a>
+</div>
+<table id='change_pw_table' class='data_grid hide_me' style='margin-left: 20px;' width='95%'>
+       <thead>
+        <tr><td colspan='2' align='center'><b>[% l("Password") %]</b></td></tr>
+    </thead>
+    <tbody>
+        <tr>
+            <td colspan='2' style='padding:10px;'>
+                [% l("This appears to be the first time you have logged in.  You will need to change your password.") %]
+                [% l("The password must be at least 7 characters in length,
+ contain at least one letter (a-z/A-Z),
+ and contain at least one number.") %]
+            </td>
+        </tr>
+        <tr>
+            <td>[% l("Enter your current password") %]</td>
+            <td><input type='password' id='change_pw_current'/></td>
+        </tr>
+        <tr>
+            <td>[% l("Enter the new password") %]</td>
+            <td><input type='password' id='change_pw_1'/></td>
+        </tr>
+        <tr>
+            <td>[% l("Re-type the new password for verification") %]</td>
+            <td><input type='password' id='change_pw_2'/></td>
+        </tr>
+        <tr><td><br/></td><td/></tr>
+        <tr class='color_1'>
+            <td colspan='2' align='center'>
+                <span class='login_text' style='margin-right: 20px;'>
+                    <input type='submit' value='[% l("Update Password") %]'  id='change_pw_button'/>
+                </span>
+            </td>
+        </tr>
+    </tbody>
+</table>
+
+
+<span id='pw_no_match' class='hide_me'>[% l("Passwords do not match") %]</span>
+<span id='pw_update_successful' class='hide_me'>[% l("Password successfully updated") %]</span>
+<span id='pw_not_strong' class='hide_me'>
+    [% l("The password provided is not strong enough.") %]
+    [% l("The password must be at least 7 characters in length, contain at least one letter (a-z/A-Z), and contain at least one number.") %]
+</span>
+
+ ^== TODO: MOVE INTO SEPARATE FORGOT-PASSWORD PAGE  -->
+
+[% IF ctx.login_failed_event %]
+<div id='login-failed-message'>
+[%
+    IF ctx.login_failed_event.textcode == 'PATRON_CARD_INACTIVE';
+        l("The barcode used to login is marked as inactive.  Please contact your local library.");
+    ELSIF ctx.login_failed_event.textcode == 'PATRON_INACTIVE';
+        l("This account has been deactivated.  Please contact your local library.");
+    ELSE;
+        l("Login failed. The username or password provided was not valid.  
+            Ensure Caps-Lock is off and try again or contact your local library.");
+    END;
+%]
+</div>
+[% END %]
+
+<div>
+    <div style="height:20px;"></div>
+    <form method='POST'>
+        <table cellpadding="0" cellspacing="0" border="0">
+            <tr>
+                <td valign="top" width="676" class="login_boxes left_brain">
+                    <table cellpadding="0" cellspacing="0" border="0"
+                        width="100%">
+                        <tr>
+                               <td colspan="2" style="padding-bottom: 10px;">
+                                <h1>[% l('Log in to Your Account') %]</h1>
+                                [% l('Please enter the following information:') %]
+                                <br /><br />
+                            </td>
+                        </tr>
+                        <tr>
+                            <td width="42%" class="lbl1">
+                                [% l('Library Card Number or Username') %]
+                                <br />
+                                <span class="lbl2">
+                                    [% l('Please include leading zeros and no spaces.') %]
+                                    <br/>
+                                    [% l('Example: 0026626051') %]
+                                </span>
+                                <br /><br />
+                            </td>
+                            <td width="58%" valign="top">
+                                <div class="input_bg">
+                                    <input type="text" id="username_field" name="username"/>
+                                </div>
+                            </td>
+                        </tr>
+                        <tr>
+                            <td colspan="2">
+                                <div style="height:15px;"></div>
+                            </td>
+                        </tr>
+                        <tr>
+                            <td valign="top" class="lbl1">
+                                [% l('PIN Number or Password') %]<br />
+                                [% INCLUDE "default/opac/parts/login/password_hint.tt2" %]
+                            </td>
+                            <td valign="top">
+                                <div class="input_bg">
+                                    <input name="password" type="password" />
+                                </div>
+                                <div style="padding-top:7px;">
+                                    [%
+                                        # If no redirect is offered or it's leading us back to the 
+                                        # login form, redirect the user to My Account
+                                        redirect = CGI.param('redirect_to') || ctx.referer;
+                                        IF !redirect OR redirect.match(ctx.path_info _ '$');
+                                            redirect = CGI.url('-full' => 1) _ '/opac/myopac/main';
+                                        END;
+                                        redirect = redirect  | replace('^http:', 'https:');
+                                    %]
+                                    <input type='hidden' name='redirect_to' value='[% redirect %]'/>
+                                    <input type="checkbox" name="persist" /> [% l('Remember Me?') %]
+                                </div>
+                                <div style="padding-top:14px;">
+                                    <input type='image' alt="[% l('Log in') %]" src="[% ctx.media_prefix %]/images/login-btn2.png" />
+                                    <!-- TODO
+                                    <a href="reset_password"
+                                        style="position:relative;top:-13px;left:2px;font-size:10px;">Forgot your PIN?</a>
+                                    -->
+                                </div>
+                               </td>
+                        </tr>
+                    </table>
+                    <br /><br />
+                </td>
+                   <td><div style="width:10px;"></div></td>
+                [% INCLUDE "default/opac/parts/login/help.tt2" %]
+            </tr>
+        </table>
+    </form>
+    <div class="clear-both"></div>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/login/help.tt2 b/Open-ILS/web/templates/default/opac/parts/login/help.tt2
new file mode 100644 (file)
index 0000000..16db31f
--- /dev/null
@@ -0,0 +1,12 @@
+<td class="login_boxes right_brain" align="center" valign="top" width="291">
+
+    <a href="http://example.com"><img 
+        src="[% ctx.media_prefix %]/images/questions.png" alt="[% l('Questions?') %]" style="margin-top:29px;" /></a>
+
+    <div style="width:182px;color:black;padding:5px 25px;">
+        [% l('Visit our FAQs section for answers to common questions about how to use your account.') %]
+    </div>
+
+    <a href="http://example.com"><img
+        alt="[% l('FAQs') %]" src="[% ctx.media_prefix %]/images/faqs-btn.png" style="margin-top:13px;" /></a>
+</td>
diff --git a/Open-ILS/web/templates/default/opac/parts/login/password_hint.tt2 b/Open-ILS/web/templates/default/opac/parts/login/password_hint.tt2
new file mode 100644 (file)
index 0000000..a95b47f
--- /dev/null
@@ -0,0 +1,5 @@
+<span class="lbl2">
+    [% | l('<br/>', '<br/>') %]
+       If this is your first time logging in, please enter [_1] the last 4 digits of your phone number. [_2] Example: 0926
+    [% END %]
+</span>
diff --git a/Open-ILS/web/templates/default/opac/parts/misc_util.tt2 b/Open-ILS/web/templates/default/opac/parts/misc_util.tt2
new file mode 100644 (file)
index 0000000..0e7cd2c
--- /dev/null
@@ -0,0 +1,75 @@
+[% 
+    # Extract MARC fields from XML
+    #   get_marc_attrs( { marc_xml => doc } )
+    BLOCK get_marc_attrs;
+        xml = args.marc_xml;
+        args.isbn = xml.findnodes('//*[@tag="020"]/*[@code="a"]').shift.textContent;
+        args.upc = xml.findnodes('//*[@tag="024"]/*[@code="a"]').textContent;
+        args.issn = xml.findnodes('//*[@tag="022"]/*[@code="a"]').textContent;
+        args.title = xml.findnodes('//*[@tag="245"]/*[@code="a"]').textContent;
+        args.author = xml.findnodes('//*[@tag="100"]/*[@code="a"]').textContent;
+        args.publisher = xml.findnodes('//*[@tag="260"]/*[@code="b"]').textContent;
+        args.pubdate = xml.findnodes('//*[@tag="260"]/*[@code="c"]').textContent;
+        args.edition = xml.findnodes('//*[@tag="250"]/*[@code="a"]').textContent ||
+            xml.findnodes('//*[@tag="534"]/*[@code="b"]').textContent ||
+            xml.findnodes('//*[@tag="775"]/*[@code="b"]').textContent;
+        phys = xml.findnodes(
+            '//*[@tag="300"]/*[@code="a" or @code="b" or @code="c" or @code="e"]'
+        );
+        phys_content = [];
+        FOR p IN phys; phys_content.push(p.textContent); END;
+        args.phys_desc = phys_content.join("");
+
+        # MARC Callnumber
+        args.marc_cn = xml.findnodes('//*[@tag="092" or @tag="099"]/*').textContent;
+
+        # clean up the ISBN
+        args.isbn_clean = args.isbn.replace('\ .*', '');
+
+        args.holdings = [];
+        FOR holding IN xml.findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]');
+            args.holdings.push(
+                holding.getAttribute('label')
+            );
+        END;
+
+        # Extract the copy count summary
+        count_type = (ctx.is_staff) ? 'staff' : 'public';
+        xpath = '//*[local-name()="counts"]/*[local-name()="count"][@type="' _ count_type _ '"]';
+        FOR node IN xml.findnodes(xpath);
+            args.copy_counts = {};
+            FOR attr IN ['count', 'available', 'unshadow', 'transcendant']; 
+                args.copy_counts.$attr = node.getAttribute(attr);
+            END;
+        END;
+
+        # "mattype" == "custom marc format specifier"
+        FOR icon_style IN ['mattype', 'item_type']; 
+            node = xml.findnodes(
+                '//*[local-name()="attributes"]/*[local-name()="field"][@name="' _ icon_style _ '"]');
+            IF node;
+                args.format_label = node.getAttribute('coded-value')
+                args.format_icon = ctx.media_prefix _ '/images/format_icons/' _ icon_style _ '/' _ node.textContent _ '.png';
+                LAST;
+            END;
+        END;
+    END;
+
+    BLOCK get_hold_status;
+        IF hold.hold.status == 4;
+            l("Available");
+            IF ahr.shelf_expire_time;
+                l('<br/>Expires [_1]', 
+                    date.format(ctx.parse_datetime(ahr.shelf_expire_time), DATE_FORMAT));
+            END;
+        ELSIF hold.hold.estimated_wait AND hold.hold.estimated_wait > 0;
+            # estimated wait is delivered as seconds.
+            SET hwait = POSIX.ceil(hold.hold.estimated_wait / 86400);
+            l("Estimated wait: [quant,_1,day,days]", hwait);
+        ELSIF hold.hold.status == 3;
+            l("In Transit");
+        ELSIF hold.hold.status < 3;
+            l("Waiting for copy");
+        END;
+    END;
+%]
diff --git a/Open-ILS/web/templates/default/opac/parts/myopac/base.tt2 b/Open-ILS/web/templates/default/opac/parts/myopac/base.tt2
new file mode 100644 (file)
index 0000000..fccb14b
--- /dev/null
@@ -0,0 +1,37 @@
+[%  WRAPPER "default/opac/parts/base.tt2" %]
+
+[% myopac_pages = [
+        {url => "main", name => "Account Summary"},
+        {url => "circs", name => "Items Checked Out"},
+        {url => "holds", name => "Holds"},
+        {url => "prefs", name => "Account Preferences"},
+        {url => "lists", name => "My Lists"}
+    ];
+    skin_root = "../"
+%]
+    [% INCLUDE "default/opac/parts/topnav.tt2" %]
+    <div id="search-wrapper">
+        [% INCLUDE "default/opac/parts/printnav.tt2" %]
+        [% INCLUDE "default/opac/parts/searchbar.tt2" %]
+    </div>
+    <div id="content-wrapper">
+        <div id="myopac_tabs">
+            <div id="acct_tabs">
+                [%- FOREACH page IN myopac_pages;
+                    IF page.url == myopac_page;
+                        cls_which = "on";
+                        ctx.page_title = "Your Account - " _ page.name;
+                    ELSE;
+                        cls_which = "off";
+                    END -%]
+                <a href="[% ctx.opac_root _ '/myopac/' _ page.url %]"
+                    class="acct-[% page.url; '-'; cls_which %] acct-tab"></a>
+                [% END %]
+            </div>
+        </div>
+        <div id="main-content">
+            [% content %]
+            <div class="common-full-pad"></div>
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/parts/myopac/main_base.tt2 b/Open-ILS/web/templates/default/opac/parts/myopac/main_base.tt2
new file mode 100644 (file)
index 0000000..0630a10
--- /dev/null
@@ -0,0 +1,100 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    PROCESS "default/opac/parts/misc_util.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2";
+%]
+
+<div id='myopac_summary_div' style="padding:0px;">
+
+    <div style="width:742px;float:left;">
+        <div class="header_middle">[% l('Account Summary') %]</div>
+    </div>
+
+    <!-- fines summary along the right of the page -->
+    [% IF myopac_main_page == "payment_form" %]
+    <div id="myopac_sum_fines_placehold"></div>
+    [% ELSE %]
+    <div id="myopac_sum_fines">
+        <div style="position:absolute;">
+            <div style="position:relative;top:-15px;left:-23px;">
+                <img src="[% ctx.media_prefix %]/images/acct_sum_fines_tl.png" />
+            </div>
+        </div>
+        <div style="position:absolute;">
+            <div style="position:relative;top:-15px;left:172px;">
+                <img src="[% ctx.media_prefix %]/images/acct_sum_fines_tr.png" />
+            </div>
+        </div>
+        <div style="position:absolute;">
+            <div style="position:relative;top:161px;left:-23px;">
+                <img src="[% ctx.media_prefix %]/images/acct_sum_fines_bl.png" />
+            </div>
+        </div>
+        <div style="position:absolute;">
+            <div style="position:relative;top:161px;left:172px;">
+                <img src="[% ctx.media_prefix %]/images/acct_sum_fines_br.png" />
+            </div>
+        </div>
+        [% l('Fines:') %]
+        <span id="myopac_sum_fines_bal" class='[% ctx.user_stats.fines.balance_owed ? "red" : ""%]'>
+            [% money(ctx.user_stats.fines.balance_owed) %]
+        </span><br />
+
+        <form action="[% ctx.opac_root %]/myopac/main_payment_form" method="POST"><input
+            type="image" title="[% l('Pay Fines') %]" alt="[% l('Pay Fines') %]"
+            onmouseover="this.src='[% ctx.media_prefix %]/images/pay-fines-btn-hover.png';"
+            onmouseout="this.src='[% ctx.media_prefix %]/images/pay-fines-btn.png';"
+            src="[% ctx.media_prefix %]/images/pay-fines-btn.png"
+            class="pos-rel-top-5" /></form>
+    </div>
+    [% END %]
+
+    <div style="width:662px;">
+        <div style="float:left;">
+            <div style="padding:10px 0px;" id="myopac_sum_name"></div>
+            <div class="acct_sum_row">
+                <table width="100%" cellspacing="0" cellpadding="0">
+                    <tr>
+                        <td>[% l("Items Currently Checked out ([_1])", ctx.user_stats.checkouts.total_out) %]</td>
+                        <td align="right">
+                            <a href="[% ctx.opac_root %]/myopac/circs">[% l("View All") %]</a>
+                        </td>
+                    </tr>
+                </table>
+            </div>
+            <div class="acct_sum_row">
+                <table width="100%" cellspacing="0" cellpadding="0">
+                    <tr>
+                        <td>[% l('Items Currently on Hold ([_1])', ctx.user_stats.holds.total) %]</td>
+                        <td align="right">
+                            <a href="[% ctx.opac_root %]/myopac/holds">[% l('View All') %]</a>
+                        </td>
+                    </tr>
+                </table>
+            </div>
+            <div class="acct_sum_row">
+                <table width="100%" cellspacing="0" cellpadding="0">
+                    <tr>
+                        <td>[% l('Items ready for pickup ([_1])', ctx.user_stats.holds.ready) %]</td>
+                        <td align="right">
+                            <a href="[% ctx.opac_root %]/myopac/holds?available=1">[% l('View All') %]</a>
+                        </td>
+                    </tr>
+                </table>
+            </div>
+        </div>
+    </div>
+    <div class="clear-both"></div>
+    <div id='fines_payments_wrapper'>
+        <div id='acct_fines_tabs'>
+            [% IF myopac_main_page == 'main' %]
+            <a href='#'><img src='[% ctx.media_prefix %]/images/acct_fines_on.jpg'/></a>
+            <a href='main_payments'><img src='[% ctx.media_prefix %]/images/acct_payments_off.jpg'/></a>
+            [% ELSE %]
+            <a href='main'><img src='[% ctx.media_prefix %]/images/acct_fines_off.jpg'/></a>
+            <a href='#'><img src='[% ctx.media_prefix %]/images/acct_payments_on.jpg'/></a>
+            [% END %]
+        </div>
+    </div>
+    [% content %]
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/parts/myopac/prefs_base.tt2 b/Open-ILS/web/templates/default/opac/parts/myopac/prefs_base.tt2
new file mode 100644 (file)
index 0000000..fb896ad
--- /dev/null
@@ -0,0 +1,56 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/myopac/base.tt2"; %]
+
+<div id='myopac_prefs_div'>
+    <div id="acct_prefs_tabs" style="padding-bottom: 12px;color:#666;">
+        <div style="float:left;">
+
+        [% IF prefs_page == 'personal' %]
+            <div class="align">
+                <a href='#'><img src="[% ctx.media_prefix %]/images/sub_prefs_info_on.jpg" /></a>
+            </div>
+            <div class="align">
+                <a href='prefs_notify'><img src="[% ctx.media_prefix %]/images/sub_prefs_notify_off.jpg" /></a>
+            </div>
+            <div class="align">
+                <a href='prefs_settings'><img src="[% ctx.media_prefix %]/images/sub_prefs_search_off.jpg" /></a>
+            </div>
+        [% ELSIF prefs_page == 'notify' %]
+            <div class="align">
+                <a href='prefs'><img src="[% ctx.media_prefix %]/images/sub_prefs_info_off.jpg" /></a>
+            </div>
+            <div class="align">
+                <a href='#'><img src="[% ctx.media_prefix %]/images/sub_prefs_notify_on.jpg" /></a>
+            </div>
+            <div class="align" >
+                <a href='prefs_settings'><img src="[% ctx.media_prefix %]/images/sub_prefs_search_off.jpg" /></a>
+            </div>
+        [% ELSE %]
+            <div class="align">
+                <a href='prefs'><img src="[% ctx.media_prefix %]/images/sub_prefs_info_off.jpg" /></a>
+            </div>
+            <div class="align">
+                <a href='prefs_notify'><img src="[% ctx.media_prefix %]/images/sub_prefs_notify_off.jpg" /></a>
+            </div>
+            <div class="align" >
+                <a href='#'><img src="[% ctx.media_prefix %]/images/sub_prefs_search_on.jpg" /></a>
+            </div>
+        [% END %]
+        </div>
+    </div> 
+
+    <div class="clear-both"></div> <br/>
+
+    <div class="header_middle">
+        <span id="acct_prefs_header">[% l('Account Information and Preferences') %]</span>
+        <span class="float-right"> 
+            <a class="hide_me" href="#">[% l('Export List') %]</a><!-- what does this do? -->
+        </span>
+    </div>
+
+    <div class="clear-both normal-height"></div>
+
+[% content; %]
+
+</div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/parts/myopac/prefs_hints.tt2 b/Open-ILS/web/templates/default/opac/parts/myopac/prefs_hints.tt2
new file mode 100644 (file)
index 0000000..e2fbc6b
--- /dev/null
@@ -0,0 +1,5 @@
+<p>
+    [% l('Ensure your account has a valid email address so that we can notify
+          you about available holds, items that are about to be overdue, and
+          overdue items!') %]
+</p>
diff --git a/Open-ILS/web/templates/default/opac/parts/org_selector.tt2 b/Open-ILS/web/templates/default/opac/parts/org_selector.tt2
new file mode 100644 (file)
index 0000000..2daf63a
--- /dev/null
@@ -0,0 +1,23 @@
+[%
+    BLOCK build_org_selector_options; %]
+        <option value='[% walker.id %]' [% IF walker.id == value %] selected='selected' [% END %]>
+            [%
+                pad = walker.ou_type.depth * 2;
+                FOR idx IN [0..pad]; '&nbsp;'; END;
+                walker.name;
+            %]
+        </option>
+        [%  FOR child IN walker.children;
+            PROCESS build_org_selector_options walker=child value=value;
+        END;
+    END;
+
+    # XXX TODO probably put this BLOCK somewhere else so it can be used widely.
+    # Org Unit Selector Widget :
+    #   PROCESS build_org_selector id='selector-id' name='selector-name'
+    BLOCK build_org_selector;
+%]
+    <select [% IF id %] id='[% id %]' [% END %] name='[% name %]'>
+    [% PROCESS build_org_selector_options walker=(org_unit || ctx.aou_tree) value=value %]
+    </select>
+[%  END %]
diff --git a/Open-ILS/web/templates/default/opac/parts/place_hold.tt2 b/Open-ILS/web/templates/default/opac/parts/place_hold.tt2
new file mode 100644 (file)
index 0000000..8f56aa5
--- /dev/null
@@ -0,0 +1,347 @@
+[%  PROCESS "default/opac/parts/misc_util.tt2";
+    attrs = {marc_xml => ctx.marc_xml};
+    PROCESS get_marc_attrs args=attrs;
+%]
+<div>
+    <div id='xulholds_box' class='hide_me canvas' style='margin-top: 6px;'>
+        <!-- XXX TODO staff will need this to work ("advanced" hold placement)
+        later -->
+        <center>
+            <table class='data_grid' style='margin-top: 20px;'>
+                <tbody>
+                    <tr>
+                        <td>[% l("Enter recipient barcode") %]:</td>
+                        <td>
+                            <input type='text' id='xul_recipient_barcode' />
+                        </td>
+                        <td>
+                            <input type='submit' value='[% l("Submit") %]'
+                                id='xul_recipient_barcode_submit' />
+                        </td>
+                        <td>
+                            <input type='submit' value='[% l("Cancel") %]' />
+                        </td>
+                        <td>
+                            <input type='submit'
+                                value='[% l("Place hold for my account") %]'
+                                id='xul_recipient_me' />
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+        </center>
+    </div>
+    <div id='check_holds_box' class='hide_me canvas' 
+        style='margin-top: 6px; width: 100%; text-align: center'>
+        <br/><br/><br/>
+        <b>[% l("Checking for possibility of hold fulfillment...") %]</b>
+    </div>
+    <div id='holds_box' class='canvas' style='margin-top: 6px;'>
+        [% IF ctx.hold_success %]
+        <div><big><strong>[% l("Hold was successfully placed"); %]</strong></big></div>
+        [% ELSIF ctx.hold_failed %]
+        <div><big><strong>[% l("Hold was not successfully placed"); %]</strong></big></div>
+            [% IF ctx.hold_failed_event %]
+        <div>
+            <strong>[% l('Problem:') %]</strong>
+            <span title="[% ctx.hold_failed_event.textcode %]">
+                <em>[% ctx.hold_failed_event.desc ||
+                        ctx.hold_failed_event.payload.fail_part ||
+                        ctx.hold_failed_event.textcode %]</em>
+            </span>
+        </div>
+            [% END;
+        ELSE %]
+        <form method="POST">
+            <br/>
+            <input type="hidden" name="hold_target"
+                value="[% CGI.param('hold_target') | html %]" />
+            <input type="hidden" name="hold_type"
+                value="[% CGI.param('hold_type') | html %]" />
+            [%
+                new_redirect_to = ctx.referer;
+                IF new_redirect_to.match('redirect_to');
+                    new_redirect_to = 'https://' _ ctx.hostname _ ctx.opac_root _ '/home';
+                ELSE;
+                    new_redirect_to = new_redirect_to | replace('^http:', 'https:');
+                END;
+            %]
+            <input type="hidden" name="redirect_to"
+                value="[% new_redirect_to | html %]" />
+            <h1>Place Hold</h1>
+            <p>
+                [% | l(attrs.title, ctx.get_aou(ctx.default_pickup_lib).name) %]
+                You would like to place a hold on <strong><q>[_1]</q></strong> to be picked up at [_2].
+                If this is correct, press <strong>SUBMIT</strong>.
+                [% END %]
+            </p>
+            <p>
+                [% l('If you would like to change the library pick up location, select from the location dropdown menu.') %]
+                <br class="clear-both" />
+                [% PROCESS "default/opac/parts/org_selector.tt2";
+                    PROCESS build_org_selector name='pickup_lib' value=ctx.default_pickup_lib %]
+            </p>
+            <p>
+                [% |l %]If you use the Traveling Library Center (TLC) and ABC Express
+                services, please select "Outreach" to have the item delivered
+                during your scheduled visit.[% END %]
+            </p>
+            <input type="image" name="submit" value="submit" title="[% l('Submit') %]"
+                alt="[% l('Submit') %]" src="[% ctx.media_prefix %]/images/btnSubmit.png" />
+            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+            <a href="javascript:history.go(-1);" id="holds_cancel"><img
+                alt="[% l('Cancel') %]" src="[% ctx.media_prefix %]/images/btnCancel.png" /></a>
+        </form>
+        <br /><br />
+        <p>
+            [% |l %]* If you need your item today, and it is checked in at your
+            library, please place your hold and then call your library to set it
+            aside. Placing a hold without calling the library will increase your
+            wait time.[% END %]
+            <br /><a href="#">[% l('Library phone numbers.') %]</a>
+        </p>
+        <p>
+            [% |l %]* For best possible service, we recommend keeping 
+            a printed copy of your most recent holds list.[% END %]
+        </p>
+        [% END %] <!-- ctx.hold_success -->
+        <table width='90%' border="1" class="hide_me">
+            <tbody>
+                <tr>
+                    <td class='holds_cell color_1' 
+                        align='center' colspan='2'>[% l("Create / Edit a Hold") %]</td>
+                </tr>
+                <tr>
+                    <td class='holds_cell'>[% l("Recipient") %]:</td>
+                    <td class='holds_cell' id='holds_recipient'> </td>
+                </tr>
+                <tr>
+                    <td class='holds_cell'>[% l("Title:") %]</td>
+                    <!-- <td class='holds_cell' id='holds_title'> </td> -->
+                </tr>
+                <tr>
+                    <td class='holds_cell'>[% l("Author") %]</td>
+                    <td class='holds_cell' id='holds_author'> </td>
+                </tr>
+                <tr>
+                    <td class='holds_cell'>[% l("Format") %]</td>
+                    <td class='holds_cell' id='holds_format'> </td>
+                </tr>
+                <tr id='hold_physical_desc_row'>
+                    <td class='holds_cell'>[% l("Physical Description:") %]</td>
+                    <td class='holds_cell' id='holds_physical_desc'> </td>
+                </tr>
+
+                <tr class='hide_me' id='holds_cn_row'>
+                    <td class='holds_cell'>[% l("Call Number:") %]</td>
+                    <td class='holds_cell'><b id='holds_cn'/> </td>
+                </tr>
+
+                <tr class='hide_me' id='holds_copy_row'>
+                    <td class='holds_cell'>[% l("Copy Barcode:") %]</td>
+                    <td class='holds_cell'><b id='holds_copy'/> </td>
+                </tr>
+
+                <tr class='hide_me' id='holds_type_row'>
+                    <td class='holds_cell'>[% l("Hold Type:") %]</td>
+                    <td class='holds_cell hide_me' id='holds_is_cn'>
+                        <b>[% l("Volume Hold") %]</b>
+                    </td>
+                    <td class='holds_cell hide_me' id='holds_is_copy'>
+                        <b>[% l("Copy Hold") %]</b>
+                    </td>
+                </tr>
+                <tr>
+                    <td class='holds_cell'>[% l("Contact telephone number") %]:</td>
+                    <td class='holds_cell'>
+                        <input id='holds_phone' size='13' maxlength='12'/>
+                        <span style='margin-left: 4px; font-size: 7pt;'>
+                            [% l("(XXX-YYY-ZZZZ)") %]
+                        </span>
+                    </td>
+                </tr>
+                <tr>
+                    <td class='holds_cell'>[% l("Enable phone notifications for this hold?") %]</td>
+                    <td class='holds_cell'>
+                        <input type='checkbox' id='holds_enable_phone'
+                            checked='checked' />
+                    </td>
+                </tr>
+                <tr>
+                    <td class='holds_cell'>[% l("Contact email address") %]:</td>
+                    <td class='holds_cell' id='holds_email'> 
+                        <span class='hide_me' id='holds.no_email'>
+                           ([% l("Patron has no configured email address") %])<br/>
+                           ([% l("See") %] <a class='classic_link' id='holds.no_email.my_account'>[% l("My Account") %]</a> [% l("for setting your email address") %])
+                        </span>
+                        <span class='hide_me' id='holds.no_email.xul'>
+                           [% l("(Patron has no configured email address)") %] 
+                        </span>
+                    </td>
+                </tr>
+                <tr>
+                    <td class='holds_cell'>[% l("Enable email notifications for this hold?") %]</td>
+                    <td class='holds_cell'>
+                        <input type='checkbox' id='holds_enable_email'
+                            checked='checked'/>
+                    </td>
+                </tr>
+                <!--
+                <tr id='holds_depth_selector_row' class='hide_me'>
+                    <td class='holds_cell'>Hold Range</td>
+                    <td class='holds_cell'>
+                        <select id='holds_depth_selector'></select>
+                    </td>
+                </tr>
+                -->
+                <tr>
+                    <td class='holds_cell'>[% l("Pickup location") %]</td>
+                    <td class='holds_cell'>
+                        <!-- <select id='holds_org_selector'> </select> -->
+                    </td>
+                </tr>
+
+                <tr>
+                    <td class='holds_cell'>[% l("Expiration date") %]</td>
+                    <td class='holds_cell'>
+                        <input size='10' maxlength='10'
+                         id='holds_expire_time' />
+                    </td>
+                </tr>
+
+                <tr>
+                    <td class='holds_cell'>
+                        [% l("Suspend this hold") %]
+                        <a class='classic_link'
+                            href='#'>[% l("(Help)") %]</a>
+                        </td>
+                    <td class='holds_cell'>
+                        <input type='checkbox' id='holds_frozen_chkbox' /> 
+                    </td>
+                </tr>
+                <tr id='hold_frozen_thaw_row' class='hide_me'>
+                    <td class='holds_cell'>
+                        <!-- XXX TODO there used to be script here dealing with
+                        frozen holds -->
+                        [% l("Automatically activate hold on:") %]
+                    </td>
+                    <td class='holds_cell'>
+                        <input size='10' maxlength='10'
+                            id='holds_frozen_thaw_input' />
+                    </td>
+                </tr>
+
+                <tr id='holds_alt_formats_row_extras' class='hide_me'>
+                    <td colspan='2' align='center'>
+                        <div style='padding: 8px;'>
+                            <a class='classic_link' href='#'
+                                style='padding: 5px;'>[% l("Advanced Hold Options") %]</a>
+                        </div>
+                    </td>
+                </tr>
+
+                <tr id='holds_alt_formats_row' class='hide_me'>
+
+                    <td class='holds_cell'>
+                        <div style='margin-bottom: 5px;'>
+                            <span>[% l("Acceptable Alternative Formats:") %] </span>
+                            <span><a class='classic_link red' href='#'>[% l("(Help)") %]</a></span>
+                        </div>
+                        <div>[% l("(control-click to select multiple formats)") %]</div>
+                    </td>
+
+                    <td class='holds_cell'>
+                        <select id='hold_alt_form_selector' multiple='multiple' style='width: 14em;'>
+                            <option value='at'    class='hide_me'>[% l("Books") %]</option>
+                            <option value='at-d' class='hide_me'>[% l("Large Print Books") %]</option>
+                            <option value='i'        class='hide_me'>[% l("Audiobooks") %]</option>
+                            <option value='g'        class='hide_me'>[% l("Video Recordings") %]</option>
+                            <option value='j'        class='hide_me'>[% l("Music") %]</option>
+                        </select>
+                    </td>
+                </tr>
+                <tr>
+                    <td class='holds_cell' align='center' colspan='2'>
+                        <!-- <button id='holds_submit'>[% l("Place Hold") %]</button> -->
+                        <button class='hide_me' id='holds_update'>[% l("Update Hold") %]</button>
+                        <span style='padding: 20px;'> </span>
+                        <!-- <button id='holds_cancel'>[% l("Cancel") %]</button> -->
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+        <div class='hide_me' id='holds_success'>[% l("Hold was successfully placed") %]</div>
+        <div class='hide_me' id='holds_failure'>[% l("Hold was not successfully placed") %]</div>
+        <span class='hide_me' id='holds_bad_phone'>
+            [% l("The phone number does not have the correct format. The expected format is XXX-YYY-ZZZZ") %]
+        </span>
+        <span class='hide_me' id='hold_not_allowed'>
+            [% |l %]No items were found that could fulfill the requested holds.  
+                It's possible that choosing a different format will result in a successful hold.  
+                It is also possible that you have exceeded the number of allowable holds.  
+                For further information, please consult your local librarian.[% END %]
+        </span>
+    </div>
+    <div id="anonListTable" class="hide_me" style="margin-top: 6px;">
+        <select id="holdsCacheSel" class="hide_me"></select><br />
+        <a href="#">Place hold on selected</a><br />
+        <a href="#">Remove selected</a>
+        
+        <table id="temp_list_holds" cellpadding='0' cellspacing='0' border='0'
+            style="margin-top:10px;">
+            <tr>
+                <td width="1%" style="padding-left:10px;">
+                    <input type='checkbox' title='Select All'
+                        id='anon_selector' />
+                </td>
+                <td width="1%">
+                </td>
+                <td width="98%" style="padding-left:40px;">
+                    <strong>Title</strong>
+                </td>
+            </tr>
+        </table>
+        <table width='100%' style="margin-left:7px;margin-bottom:10px;">
+            <thead>
+                <tr><td width='20'></td><td width='30'></td><td></td></tr>
+            </thead>
+            <tbody id="anonListParent">
+                <tr id="anonListTemp">
+                  <td><input type='checkbox' name='anon_selector' /></td>
+                  <td name="curr_row"></td>
+                  <td name="title"></td>
+                </tr>
+            </tbody>
+        </table>
+        <a href="#">Back to search results</a>
+    </div>
+
+    <span class='hide_me' id='format_words'>
+        <span name='at'>[% l("Books") %]</span>
+        <span name='at-d'>[% l("Large Print Books") %]</span>
+        <span name='i'>[% l("Audiobooks") %]</span>
+        <span name='g'>[% l("Video Recordings") %]</span>
+        <span name='j'>[% l("Music") %]</span>
+        <span name='m'>[% l("Electronic Resources") %]</span>
+    </span>
+
+    <span class='hide_me' id='holds_explain_adv'>
+        [% |l %]If you wish to broaden the scope of your hold to include other versions of this title, 
+        select the formats that would be acceptable.  The first available copy will be sent to you.[% END %]
+    </span>
+
+    <span class='hide_me' id='holds_pick_good_org'>[% l("Please select a physical location where your hold can be delivered.") %]</span>
+    <span class='hide_me' id='hold_dup_exists'>[% l("A hold already exists on the requested item.") %]</span>
+    <span class='hide_me' id='hold_dup_exists_override'>[% l("A hold already exists on the requested item. Would you like to create the hold anyway?") %]</span>
+
+    <span id='hold_failed_patron_barred' class='hide_me'>
+        [% |l %]PATRON BARRED. Please see any notes in the "Staff Notes" section of your 
+        "My Account" page or contact your local library.[% END %]
+    </span>
+
+    <span id='invalid_hold' class='hide_me'>
+        [% |l %]This hold is no longer valid. It's likely that the target for the hold was 
+        deleted from the system.  Please cancel this hold and place a new one.[% END %]
+    </span>
+    <span id='holds_invalid_recipient' class='hide_me'>[% l("The patron barcode entered as the hold recipient is invalid.") %]</span>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/printnav.tt2 b/Open-ILS/web/templates/default/opac/parts/printnav.tt2
new file mode 100644 (file)
index 0000000..580c0d6
--- /dev/null
@@ -0,0 +1,25 @@
+<div class="big-block">
+    <div class="float-right">
+        <div class="pos-rel">
+            <img src="[% ctx.media_prefix %]/images/utils-corner-left.png" class="float-left" />
+            <div class="left-corner"> 
+                <a href="javascript:history.go(-1)"
+                    id="util_back_btn"><img alt="[% l('Back') %]"
+                    src="[% ctx.media_prefix %]/images/tool_back.png" /></a>
+                <a href="[% ctx.opac_root %]/home"
+                    id="util_home_btn"><img alt="[% l('Homepage') %]"
+                    src="[% ctx.media_prefix %]/images/tool_home.png" /></a>
+                <a href="javascript:window.print();"
+                    id="util_print_btn"><img alt="[% l('Print Page') %]"
+                    src="[% ctx.media_prefix %]/images/tool_print.png" /></a>
+                <a href="http://open-ils.org/dokuwiki/doku.php?id=evergreen-user:opac_help"
+                    id="util_help_btn"><img alt="[% l('Help') %]"
+                    src="[% ctx.media_prefix %]/images/tool_help.png" /></a>
+                <a href="javascript:history.go(+1)"
+                    id="util_forw_btn"><img alt="[% l('Forward') %]"
+                    src="[% ctx.media_prefix %]/images/tool_forward.png" /></a>
+            </div>
+            <img src="[% ctx.media_prefix %]/images/utils-corner-right.png" class="float-left" />
+        </div>
+    </div>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/qtype_selector.tt2 b/Open-ILS/web/templates/default/opac/parts/qtype_selector.tt2
new file mode 100644 (file)
index 0000000..8c31f0d
--- /dev/null
@@ -0,0 +1,16 @@
+[%  query_types = [
+    {value => "keyword", label => l("Keyword")},
+    {value => "title", label => l("Title")},
+    {value => "author", label => l("Author")},
+    {value => "subject", label => l("Subject")},
+    {value => "series", label => l("Series")},
+    {value => "id|bibcn", label => l("Call Number")}
+] %]
+<select name="qtype">
+    [%  query_type = query_type || CGI.param('qtype');
+        FOR qt IN query_types -%]
+    <option value='[% qt.value %]'[%
+        query_type == qt.value ? ' selected="selected"' : ''
+    %]>[% qt.label %]</option>
+    [% END -%]
+</select>
diff --git a/Open-ILS/web/templates/default/opac/parts/record/authors.tt2 b/Open-ILS/web/templates/default/opac/parts/record/authors.tt2
new file mode 100644 (file)
index 0000000..93a8b83
--- /dev/null
@@ -0,0 +1,51 @@
+[%  
+
+authors = [
+    {
+        type => 'author', 
+        label => l('Authors: '),
+        xpath => '//*[@tag="100"]|//*[@tag="110"]|//*[@tag="111"]'
+    }, {
+        type => 'added', 
+        label => l('Added Authors: '),
+        xpath => '//*[@tag="700"]|//*[@tag="710"]|//*[@tag="711"]'
+    }, {
+        type => 'credits', 
+        label => l('Credits: '),
+        xpath => '//*[@tag="100"]|//*[@tag="110"]|//*[@tag="111"]'
+    }, {
+        type => 'cast', 
+        label => l('Cast: '),
+        xpath => '//*[@tag="508"]'
+    }, {
+        type => 'notes', 
+        label => l('Author Notes: '),
+        xpath => '' # Comes from added content...
+    }
+];
+
+BLOCK build_author_links;
+    FOR node IN ctx.marc_xml.findnodes(xpath);
+        FOR subfield IN node.childNodes;
+            NEXT UNLESS subfield.nodeName == "subfield";
+            code = subfield.getAttribute('code');
+            NEXT UNLESS code.match('[a-z]');
+            term = subfield.textContent | html;
+            '<br/><a href="' _ ctx.opac_root _ '/results?qtype=author&amp;query=' _ term _ '&amp;loc=' _ loc _ '">' _ term _ '</a>';
+        END;
+    END;
+END;
+%]
+
+<div id='rdetail_authors_div' class='rdetail_extras_div'>
+[% FOREACH author IN authors;
+    NEXT UNLESS author.xpath; 
+    links = PROCESS build_author_links(xpath=author.xpath);
+    IF links.match('\S') %]
+    <strong>[% author.label %]</strong>
+    <div class='rdetail-author-div'>[% links %]</div>
+    [% END %]
+[% END %]
+</div>
+
+
diff --git a/Open-ILS/web/templates/default/opac/parts/record/body.tt2 b/Open-ILS/web/templates/default/opac/parts/record/body.tt2
new file mode 100644 (file)
index 0000000..3444a59
--- /dev/null
@@ -0,0 +1,48 @@
+<!-- ****************** page_rdetail.xml ***************************** -->
+[%  attrs = {marc_xml => ctx.marc_xml};
+    PROCESS "default/opac/parts/misc_util.tt2";
+    PROCESS get_marc_attrs args=attrs %]
+<div id='canvas_main' class='canvas'>
+    <div id="rdetail_header" class="hide_me">[%#
+        XXX Does it make sense for now to even have this section?  Why
+        should the record detail page be aware of the ongoing search?
+        The user can use the back button to go back to their search results
+        like on any other website. %]
+        <div style="float:left;">
+            Search Results&nbsp;&nbsp;&nbsp;
+            <span id="rdetail_result_count" class="hide_me">
+                Showing Item <strong id='np_offset'></strong>
+                &nbsp;of&nbsp;<strong id='np_count'></strong>
+            </span>
+        </div>
+        <div id="rdetail_result_nav">
+            <span class="hide_me">
+                <a class='np_nav_link classic_link' id='np_start'
+                    href='#'
+                    title="[% l("First results page") %]">[% l("Start") %]</a>
+                </span>
+                <a class='np_nav_link classic_link hide_me' id='np_prev'
+                    href='#'
+                    title='[% l("Previous page") %]'><span
+                        class="nav_arrow_fix">&#9668;</span> Previous</a>
+                <span style="padding:0px 10px;"> </span>
+                <a class='np_nav_link classic_link hide_me' id='np_next'
+                    href='#'
+                    title='[% l("Next page") %]'>Next <span
+                        class="nav_arrow_fix">&#9658;</span></a>
+                <span class="hide_me"><a class='np_nav_link classic_link'
+                    id='np_end' href='#'
+                    title="[% l("Last results page") %]">[% l("End") %]</a></span>
+        </div>
+        <div class="clear-both"></div>
+    </div>
+
+    <div style='font-weight: bold; padding: 5px; margin: 5px; width: 100%;'
+        class='hide_me color_4' id='rdetail_deleted_exp'>
+        [% l("This record has been deleted from the database.  We recommend that you remove this title from any bookbags it may have been added to.") %]
+    </div>
+    [% INCLUDE "default/opac/parts/record/summary.tt2" %]
+    <br />
+    [% INCLUDE "default/opac/parts/record/extras.tt2" %]
+</div>
+<!-- ****************** end; page_rdetail.xml ***************************** -->
diff --git a/Open-ILS/web/templates/default/opac/parts/record/cn_details.tt2 b/Open-ILS/web/templates/default/opac/parts/record/cn_details.tt2
new file mode 100644 (file)
index 0000000..2865026
--- /dev/null
@@ -0,0 +1,91 @@
+<table class="hide_me">
+    <tbody>
+        <tr class='opac-auto-009' id='rdetail_volume_details_row' templateRow='1'>
+            <td colspan='10'>
+                <div style='text-align: center; margin-top: 6px; margin-bottom: 6px'>
+                    <a name='print' href='#' class='classic_link'>[% l("print these details") %]</a>
+                    <table class='data_grid data_grid_center' style='width: 100%'>
+                        <tbody name='copies_tbody' class='copy_details_table' width='100%'>
+
+                                <!-- XXX keeping for now for reference...
+                                <td>
+                                    <span name='barcode'> </span>
+                                    <a class='hide_me classic_link copy_more_info'
+                                        name='details_link'>[% l("more info...") %]</a>
+                                    <a class='hide_me classic_link copy_more_info'
+                                        name='less_details_link'>[% l("less info") %]</a>
+                                    <a class='hide_me classic_link copy_more_info'
+                                        name='copy_hold_link' href='#'>[% l("place hold") %]</a>
+                                </td>
+                                <td name='status'> </td>
+                                <td name='location'> </td>
+                                <td name='age_protect_value' class='hide_me'>[% l("- Disabled -") %]</td>
+                                <td name='create_date_value' class='hide_me'> </td>
+                                <td name='copy_holdable_td' class='hide_me'>
+                                    <span name='copy_is_holdable'> </span>
+                                </td>
+                                <td name='copy_due_date_td' class='hide_me'>
+                                    <span name='copy_due_date'> </span>
+                                </td>
+                            </tr>
+                                -->
+
+                            <tr name='copy_extras_row' class='hide_me'>
+                                <td colspan='10'>
+                                    <table width='100%' class='data_grid'>
+                                        <tbody name='extras_tbody'>
+                                            <tr name='extras_row' class='hide_me'>
+                                                <td name='type' width='20%'>
+                                                    <span name='note' class='hide_me'>
+                                                        <b>[% l("Copy Note") %]</b>
+                                                    </span>
+                                                    <span name='cat' class='hide_me'>
+                                                        <b>[% l("Copy Category") %]</b>
+                                                    </span>
+                                                </td>
+                                                <td>
+                                                    <span name='key'> </span> : <span name='value'> </span>
+                                                </td>
+                                            </tr>
+                                        </tbody>
+                                    </table>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </td>
+        </tr>
+    </tbody>
+</table>
+
+<span class='hide_me' id='rdetail.yes'>[% l("Yes") %]</span>
+<span class='hide_me' id='rdetail.no'>[% l("No") %]</span>
+
+<div id='rdetail_print_details' class='hide_me'>
+    <div style='text-align: center; padding: 20px; width: 100%'>
+        <div style='width:100%; border: 2px solid #E0F0E0; margin-bottom: 20px;'>
+            <input type='submit' value='[% l("Print Page") %]' onclick='window.print();' />
+        </div>
+        <div name='body'>
+            <table>
+                <tbody name='tbody'>
+                    <tr><td>[% l("Library") %]</td><td colspan='2' name='lib'></td></tr>
+                    <tr><td>[% l("Title") %]</td><td colspan='2' name='title'></td></tr>
+                    <tr><td>[% l("Author") %]</td><td colspan='2' name='author'></td></tr>
+                    <tr><td>[% l("Edition") %]</td><td colspan='2' name='edition'></td></tr>
+                    <tr><td>[% l("Publication Date") %]</td><td colspan='2' name='pubdate'></td></tr>
+                    <tr><td>[% l("Publisher") %]</td><td colspan='2' name='publisher'></td></tr>
+                    <tr><td>[% l("Physical Description") %]</td><td colspan='2' name='phys'></td></tr>
+                    <tr>
+                        <td colspan='3' class='opac-auto-004'> </td>
+                    </tr>
+                    <tr name='cnrow'>
+                        <td><b>[% l("Call Number") %]</b></td>
+                        <td><b colspan='2' name='cn'></b></td>
+                    </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/record/copyinfo.tt2 b/Open-ILS/web/templates/default/opac/parts/record/copyinfo.tt2
new file mode 100644 (file)
index 0000000..9d4673f
--- /dev/null
@@ -0,0 +1,68 @@
+<!-- ****************** rdetail_copyinfo.xml ***************************** -->
+<div id='rdetail_copy_info_div' class='rdetail_extras_div hide_me'>
+    <div style='width: 100%; text-align: center; padding-bottom: 5px;'>
+        <span>
+            <a href='javascript:void(0);' id='copy_info_local_link' 
+                class='rdetail_copy_nav_link hide_me classic_link'><b>[% l("View Copy Information for this location only") %]</b></a>
+        </span>
+        <span width=''>
+            <a href='javascript:void(0);' id='copy_info_all_link' 
+                class='rdetail_copy_nav_link classic_link'><b>[% l("View copy information for all libraries") %]</b></a>
+        </span>
+    </div>
+    <table id='rdetail_copy_info_table' class='data_grid'>
+        <thead>
+            <tr>
+                <td class='rdetail_copy_info_header_cell'>[% l("Library") %]</td>
+                <td class='rdetail_copy_info_header_cell'>[% l("Callnumber") %]</td>
+                <td name='rdetail_copylocation_header' class='rdetail_copy_info_header_cell hide_me'>
+                    [% l("Copy Location") %]
+                </td>
+                <td class='rdetail_copy_info_header_cell'>[% l("Actions") %]</td>
+                <td nowrap='nowrap' class='rdetail_copy_info_header_cell' id='rdetail_copy_info_status'> 
+                    <div name='rdetail_status_cell'> </div>
+                </td>
+            </tr>
+        </thead>
+        <tbody id='rdetail_copy_info_tbody'>
+            <tr id='rdetail_copy_info_row' class='hide_me'>
+                <td name='rdetail_library_cell'>
+                    <a name='lib_print_link' class='hide_me classic_link'
+                        style='font-size: 8pt; padding-left: 20px;'>[% l("Print Call Numbers for this library") %]</a>
+                </td>
+                <td name='rdetail_callnumber_cell'> </td>
+                <td class="hide_me" name='rdetail_copylocation_cell'> </td>
+                <td name='rdetail_actions_cell'> 
+                    <div style='padding-bottom: 1px;'>
+                        <a style='font-size: 8pt;'
+                            name='details' class='hide_me classic_link'>[% l("Copy Details") %]</a>
+                    </div>
+                    <div style='margin-top: 2px;'>
+                        <a name='browse' style='font-size: 8pt;'
+                            class='hide_me classic_link'>[% l("Browse Call Numbers") %]</a>
+                    </div>
+                    <div style='margin-top: 2px;' name='hold_div' class='hide_me'>
+                        <a name='hold' style='font-size: 8pt;' href='javascript:void(0);'
+                            class='classic_link'>[% l("Place Hold") %]</a>
+                    </div>
+                </td>
+                <td nowrap='nowrap' class='rdetail_copy_count_cell vertical' 
+                    name='rdetail_copy_count_cell'>
+                </td>
+            </tr>
+            <tr id='rdetail_copy_info_loading'>
+                <td>
+                    [% l("Loading copy information...") %]
+                </td>
+            </tr>
+        </tbody>
+    </table>
+    <!-- <table class='hide_me'>
+        <tbody>
+        <tr class='opac-auto-009' id='rdetail_volume_details_row'><td colspan='10'></td></tr>
+        </tbody>
+    </table> -->
+    <br/><br/>
+    <div id='rdetail_copy_info_none' class='hide_me'>[% l(" * There are no copies in this location") %]</div>
+</div> <!-- copy info -->
+<!-- ****************** end: rdetail_copyinfo.xml ***************************** -->
diff --git a/Open-ILS/web/templates/default/opac/parts/record/extras.tt2 b/Open-ILS/web/templates/default/opac/parts/record/extras.tt2
new file mode 100644 (file)
index 0000000..b101603
--- /dev/null
@@ -0,0 +1,79 @@
+<div id="rdetail_main_div">
+    <div id='rdetail_extras_div' style='width: 100%;'> 
+        <!-- SAMPLE AWARDS LAYOUT / MOVE TO INCLUDE'D TEMPLATE
+        <div id='rdetail_awards_div' class='rdetail_extras_div hide_me'> 
+            <strong>[% l('Awards:') %]</strong>
+            <div id='rdetail_awards_cont' style="margin-bottom:20px;"></div>
+                <strong>[% l('Patron Reviews:') %]</strong>
+                <div id='rdetail_chilifresh_reviews' class='hide_me' style="margin-bottom:20px;">
+                    <div id='chilifreshReviewLink' name='chilifreshReviewLink' class='chili_review'></div>
+                    <div id='chilifreshReviewResult' name='chilifreshReviewResult' class='hidden'></div>
+                </div>
+                <strong>[% l('Reviews:') %]</strong>
+                <div id='rdetail_review_container' style="margin-bottom:20px;"></div>
+                <strong>[% l('Suggested Reads:') %]</strong>
+                <div id='rdetail_novelist_div' class='rdetail_extras_div'>
+                <div id="NoveListSelect" class="NoveListSelect">
+                    <div id="NoveListAnchor" class="NoveListSelect"></div>
+                    <div id="novsuggestions"></div>
+                    <div id="nextreads"></div>
+                    <div id="novrelatedauthors"></div>
+                    <div id="novrelateditems"></div>
+                </div>
+            </div>
+        </div>
+        -->
+
+        [%  # Hidden extras are not yet implemented.  Some may require JS
+
+        extras = [
+            {name => 'summary',  label => l('Summary &amp; More'), hide => 1}, # Content Cafe
+            {name => 'content',  label => l('Contents'), hide => 1}, # ToC
+            {name => 'authors',  label => l('Authors')}, 
+            {name => 'series',   label => l('Series'), hide => 1}, 
+            {name => 'awards',   label => l('Series'), hide => 1}, 
+            {name => 'subjects', label => l('Subject')}, 
+            {name => 'annotation', label => l('Annotation'), hide => 1}, 
+            {name => 'reviews',  label => l('Reviews'), hide => 1}, 
+            {name => 'excerpt',  label => l('Excerpt'), hide => 1},
+            {name => 'issues',   label => l('Issues Held'), hide => !ctx.have_holdings_to_show},
+            {name => 'preview',  label => l('Preview'), hide => 1}, 
+            {name => 'novelist', label => l('Suggestions by NoveList'), hide => 1},
+            {name => 'cnbrowse', label => l('Shelf Browser'), hide => 1},
+            {name => 'copyinfo', label => l('Copy Summary'), hide => 1}, 
+            {name => 'marchtml', label => l('MARC Record')}
+        ];
+
+        FOREACH extra IN extras;
+            IF extra.hide; NEXT; END; 
+            name = extra.name;
+        %]
+        <div class="rdetail_extras">
+            <div class="rdetail_extras_hr"></div>
+            <div class="rdetail_extras_link">
+                [% href = ctx.full_path _ '?expand=' _ name _ '#' _ name; %]
+                <a name='[% name %]' href='[% href %]'><img
+                    alt='[% extra.label %]' src="[% ctx.media_prefix %]/images/rdetail_arrow.png" /></a>
+                <a href='[% href %]' class="rdetail_extras_lbl">[% extra.label %]</a>
+            </div>
+        </div>
+        <div class='rdetail_extras_div'>
+            [%  exp_name = 'expand_' _ name;
+                IF ctx.$exp_name;
+                    IF name == 'marchtml';
+                        ctx.marchtml;
+                    ELSE;
+                        # Load the template for the selected extra
+                        INCLUDE "default/opac/parts/record/${name}.tt2";
+                    END;
+                END; 
+            %]
+        </div>
+        [% END %]
+    </div>
+    <!--
+    <div id='rdetail_preview_full_text' class='hide_me'>[% l("Full text") %]</div>
+    <div id='rdetail_preview_title' class='hide_me'>[% l("See the full text of this book.") %]</div>
+    <div id='rdetail_preview_badge' class='hide_me'>[% l("Show a preview of this book from Google Book Search") %]</div>
+    -->
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/record/issues.tt2 b/Open-ILS/web/templates/default/opac/parts/record/issues.tt2
new file mode 100644 (file)
index 0000000..4f9f295
--- /dev/null
@@ -0,0 +1,26 @@
+<div id='rdetail_issues_div' class='rdetail_extras_div'>
+[%
+base_expando = ctx.full_path _ "?expand=issues";
+FOREACH type IN ctx.holding_summaries.keys;
+    NEXT UNLESS ctx.holding_summaries.$type.size;
+    expanded = CGI.param('expand_holding_type') == type; %]
+    <div class="rdetail-issue-type">
+        <a href="[% base_expando; expanded ? '' : '&amp;expand_holding_type=' _ type; %]#issues">[[% expanded ? '-' : '+' %]]</a>
+        [% ctx.holding_summaries.$type.join(", ") %]
+        [% IF expanded %]
+        <table>
+            [% FOR blob IN ctx.expanded_holdings %]
+            <tr>
+                <td class="rdetail-issue-issue">[% blob.issuance.label %]</td>
+                [% IF blob.has_units %]
+                <td class="rdetail-issue-place-hold">
+                    <a href="[% ctx.opac_root %]/place_hold?hold_target=[% blob.issuance.id %]&amp;hold_type=I">[% l("Place Hold") %]</a>
+                </td>
+                [% END %]
+            </tr>
+            [% END %]
+        </table>
+        [% END %]
+    </div>
+[% END %]
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/record/subjects.tt2 b/Open-ILS/web/templates/default/opac/parts/record/subjects.tt2
new file mode 100644 (file)
index 0000000..7819187
--- /dev/null
@@ -0,0 +1,67 @@
+[% 
+    subjects = [
+        {
+            label => l('Genre: '),
+            xpath => '//*[@tag="655"]|//*[@tag="659"]'
+        }, {
+            label => l('Topic Heading: '),
+            xpath => '//*[@tag="690"]'
+        }, {
+            label => l('Geographic Setting: '),
+            xpath => '//*[@tag="691"]'
+        }, {
+            label => l('Biographical Subject: '),
+            xpath => '//*[@tag="692"]'
+        }, {
+            label => l('Character Attributes: '),
+            xpath => '//*[@tag="693"]'
+        }, {
+            label => l('Setting: '),
+            xpath => '//*[@tag="698"]'
+        }, {
+            label => l('Time Period: '),
+            xpath => '//*[@tag="699"]'
+        }
+    ];
+
+    BLOCK render_subject;
+        loc = CGI.param('loc') | uri;
+        xpath = xpath || '//*[starts-with(@tag,"6")]';
+        FOR node IN ctx.marc_xml.findnodes(xpath);
+            all_terms = [];
+            FOR subfield IN node.childNodes;
+                NEXT UNLESS subfield.nodeName == "subfield";
+                code = subfield.getAttribute('code');
+                NEXT UNLESS code.match('[a-z]');
+                IF code.match('[vxyz]'); " &mdash; "; END;
+                # at this point, we actually have a partial term to use.
+                single_term = subfield.textContent | html;
+                all_terms.push(subfield.textContent);
+                total_term = all_terms.join(" ").replace('\s+$', '') | uri;
+                '<a href="' _ ctx.opac_root _ '/results?qtype=subject&amp;query=' _ total_term _ '&amp;loc=' _ loc _ '">' _ single_term _ '</a>';
+            END;
+            IF all_terms.size; "<br/>"; END;
+        END;
+    END 
+%]
+
+<div id='rdetail_subject_div'>
+    <table cellpadding="0" cellspacing="0" border="0">
+    [%  any_subjects = 0;
+        FOREACH subj IN subjects;
+            content = PROCESS render_subject(xpath=subj.xpath);
+            IF content.match('\S');
+                any_subjects = 1; %]
+            <tr>
+                <td width="1" style="padding:5px 7px 0px 0px;" valign="top">
+                    <strong>[% subj.label %]</strong>
+                </td>
+                <td style="padding-top:5px;"><div>[% content %] </div></td>
+            </tr>
+            [% END; %]
+        [% END; %]
+    [% IF any_subjects == 0 %]
+        <tr><td><i>[% l('No Subjects') %]</i></td></tr>
+    [% END; %]
+    </table>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/record/summary.tt2 b/Open-ILS/web/templates/default/opac/parts/record/summary.tt2
new file mode 100644 (file)
index 0000000..c34cf9a
--- /dev/null
@@ -0,0 +1,244 @@
+<!-- ****************** rdetail_summary.xml ***************************** -->
+<abbr class="unapi-id" title='tag:[% ctx.hostname %],[% date.format(date.now, '%Y') %]:biblio-record_entry/[% ctx.bre_id %]'></abbr>
+<!-- This holds the record summary information -->
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0" id="rdetail_details_table">
+    <tbody id="rdetail_details_tbody">
+        <tr>
+            <td width="90" valign="top" id="rdetail_image_cell">
+                [% ident = attrs.isbn_clean || attrs.upc; IF ident; %]
+                <a id='rdetail_img_link' href='[% ctx.media_prefix %]/opac/extras/ac/jacket/large/[% ident %]'><img
+                    alt="[% l('Image of item') %]" id='rdetail_image'
+                    src='[% ctx.media_prefix %]/opac/extras/ac/jacket/medium/[% ident %]' /></a>
+                [% END %]
+                <br />
+                <div class='jacket_attrib hide_me' id='rdetail.jacket_attrib_div'>
+                    <div>[% l("Image provided by") %]</div>
+                    <div>
+                        <a target='_blank' href='[% l("http://amazon.com/dp/") %]'
+                            class='classic_link' id='rdetail.jacket_attrib_link'>[% l("Amazon") %]</a>
+                    </div>
+                </div>
+            </td>
+    
+            <td valign="top">
+                <table border="0" cellpadding="0" cellspacing="0" width="100%">
+                    <tr>
+                        <td valign="top">
+                            <span id='rdetail_title'>[% attrs.title %]</span><br />
+                            [% IF attrs.author %]
+                            <span class='opac-auto-030'>[% l("Author") %]:</span>
+                            <em><a title='[% l("Perform an author search") %]'
+                                    id='rdetail_author'
+                                    href="[% ctx.opac_root %]/results?qtype=author&amp;query=[%-
+                                        attrs.author | replace('[,\.:;]', '') | uri %]&amp;loc=[% CGI.param('loc') | uri %]">[% attrs.author %]</a></em>
+                            [% END %]
+                        </td>
+                        <td align="right" valign="top" nowrap="nowrap" style="white-space:nowrap;">
+                            <div style="width:230px;text-align:left;margin-top:3px;">
+                                <div style="float:right;">
+                                    <div class="rdetail_aux_utils opac-auto-010">
+                                        <a href="[% ctx.opac_root %]/place_hold[%-
+                                            propagator; propagator.length > 1 ? "&amp;" : ""; %]hold_target=[% ctx.bre_id %]&amp;hold_type=T" id="rdetail_place_hold" class="no-dec"><img
+                                            src="[% ctx.media_prefix %]/images/green_check.png" alt="[% l('place hold') %]" /><span 
+                                                style="position:relative;top:-3px;left:3px;">[% l('Place Hold') %]</span></a>
+                                    </div>
+                                    <div class="rdetail_aux_utils opac-auto-121">
+                                        [%  
+                                            operation = ctx.mylist.grep(ctx.bre_id).size ? "delete" : "add";
+                                            label = (operation == "add") ? l("Add to my list") : l("Remove from my list"); 
+                                        %]
+                                        <form action="[% ctx.opac_root %]/mylist/[% operation %]" method="POST">
+                                            <input type="hidden" name="record" value="[% ctx.bre_id %]" />
+                                            <div class="pos-abs">
+                                                <div class="opac-auto-149">
+                                                    <input type="submit" title="[% label %]" value="[% label %]" class="subtle-button" />
+                                                </div>
+                                            </div>
+                                            <input type="image" alt="[% label %]"
+                                                src="[% ctx.media_prefix %]/images/clipboard.png" />
+                                        </form>
+                                    </div>
+                                </div>
+                                <div style="float:right;margin-right:17px;">
+                                    [% IF attrs.format_icon %]
+                                    <img alt="[% attrs.format_label %]" title="[% attrs.format_label %]" src="[% attrs.format_icon %]" />
+                                    [% END %]
+                                </div>
+                            </div>
+                        </td>
+                    </tr>
+                </table>
+                <div class='opac-auto-018'>
+                    <table border="0" cellpadding="0" width="100%">
+                        <tr>
+                            <td nowrap='nowrap' valign="top">
+                                [% IF attrs.isbn %]<strong id="rdetail_isbn_lbl">[% l("ISBN") %]</strong>[% END %]
+                            </td>
+                            <td valign="top" id='rdetail_isbn'>[% attrs.isbn %]</td>
+                            <td nowrap='nowrap' valign="top">
+                                [% IF attrs.phys_desc %]<strong id="rdetail_phys_lbl">[% l("Physical Description") %]</strong>[% END %]
+                            </td>
+                            <td valign="top" id='rdetail_physical_desc'>[% attrs.phys_desc %]</td>
+                        </tr>
+                        <tr>
+                            <td nowrap='nowrap' valign="top">
+                                <strong id="rdetail_ed_lbl">[% IF attrs.edition; l("Edition"); END %]</strong>
+                            </td>
+                            <td valign="top" id='rdetail_edition'>[% attrs.edition %]</td>
+                        </tr>
+                        <tr>
+                            <td nowrap='nowrap' valign="top">
+                                <strong id="rdetail_pub_lbl">[% IF attrs.publisher; l("Publisher"); END %]</strong>
+                            </td>
+                            <td valign="top" id='rdetail_publisher'>[% attrs.publisher %]</td>
+                            <td nowrap='nowrap' valign="top">
+                                <strong id="rdetail_pubdate_lbl">[% IF attrs.pubdate; l("Publication Date"); END %]</strong>
+                            </td>
+                            <td valign="top" id='rdetail_pubdate'>[% attrs.pubdate %]</td>
+                        </tr>
+                    </table>
+                </div>
+            </td>
+        </tr>
+    </tbody>
+</table>
+<br /><br />
+
+<table cellpadding="0" cellspacing="0" border="0" width="100%" id="rdetails_status">
+    <thead>
+        <tr id="rdetails_status_head">
+            <td>[% l("Location") %]</td>
+            <td>[% l("Call Number") %]</td>
+            <td>[% l("Barcode") %]</td>
+            <td>[% l("Shelving Location") %]</td>
+            [% IF ctx.is_staff %]
+            <td>[% l("Age Hold Protection") %]</td>
+            <td>[% l("Create Date") %]</td>
+            <td>[% l("Holdable") %]</td>
+            [% END %]
+            <td>[% l("Status") %]</td>
+            <td>[% l("Due Date") %]</td>
+        </tr>
+    </thead>
+    <tbody class="copy_details_table">
+        [% FOR copy_info IN ctx.copies %]
+        <tr>
+            <td>[%
+                # XXX KCLS-specific kludging
+                org_name = ctx.get_aou(copy_info.circ_lib).name;
+                dir = org_name | lower | replace('[^\w]', '') |
+                    replace('.+320th', '320th'); %]
+                <a href="http://www.kcls.org/[% dir %]/"
+                    class="classic_link">[% org_name %]</a>
+            </td>
+            <td>[% copy_info.call_number_label %]</td>
+            <td>[% copy_info.barcode %]</td>
+            <td>[% copy_info.copy_location %]</td>
+            [% IF ctx.is_staff %]
+            <td>
+                [% copy_info.age_protect ?
+                    ctx.get_crahp(copy_info.age_protect).name : l('None') %]
+            </td>
+            <td>[% date.format(
+                ctx.parse_datetime(copy_info.create_date),
+                DATE_FORMAT
+            ) %]</td>
+            <td>[% (copy_info.holdable == 't' AND
+                    copy_info.location_holdable == 't' AND
+                    copy_info.status_holdable == 't') ? l('Yes') : l('No') %]</td>
+            [% END %]
+            <td>[% copy_info.copy_status %]</td>
+            <td>[%
+                IF copy_info.due_date;
+                    date.format(
+                        ctx.parse_datetime(copy_info.due_date),
+                        DATE_FORMAT
+                    );
+                ELSE;
+                    '-';
+                END %]</td>
+        </tr>
+        [% END %]
+        <tr>
+        [% IF ctx.copy_offset > 0;
+            new_offset = ctx.copy_offset - ctx.copy_limit;
+            IF new_offset < 0; new_offset = 0; END %]
+            <td>
+                <a href="[% ctx.opac_root %]/record/[% ctx.bre_id %]?copy_offset=[% new_offset %]&amp;copy_limit=[% ctx.copy_limit %]">&laquo; [%
+                    l('Previous [_1]', ctx.copy_offset - new_offset)
+                %]</a>
+            </td>
+        [% END %]
+        [% IF ctx.copies.size >= ctx.copy_limit %]
+            <td>
+                <a href="[% ctx.opac_root %]/record/[% ctx.bre_id %]?copy_offset=[% ctx.copy_offset + ctx.copy_limit %]&amp;copy_limit=[% ctx.copy_limit %]">[%
+                    l('Next [_1]', ctx.copy_limit)
+                %] &raquo;</a>
+            </td>
+        [% END %]
+        </tr>
+    </tbody>
+</table>
+
+<div id="rdetail_locs_expand" class="hide_me">
+    <a href="#"><img
+        src="[% ctx.media_prefix %]/images/plus_sign.png" /></a>
+    <a style="position:relative;top:-3px;" href="#">[% l('Show more locations') %]</a>
+</div>
+
+<div id="rdetail_locs_collapse" class="hide_me">
+    <a href="#"><img
+        src="[% ctx.media_prefix %]/images/plus_sign.png" /></a>
+    <a style="position:relative;top:-3px;" href="#">[% l('Collapse locations') %]</a>
+</div>
+
+<div id="rdetail_extras_expand" class="hide_me">
+    <a href="#"><img
+        src="[% ctx.media_prefix %]/images/plus_sign.png" /></a>
+    <a style="position:relative;top:-3px;" href="#">[% l('Expand all tabs') %]</a>
+</div>
+
+<div id="rdetail_extras_collapse" class="hide_me">
+    <a href="#"><img src="[% ctx.media_prefix %]/images/plus_sign.png" /></a>
+    <a style="position:relative;top:-3px;" href="#">[% l('Collapse all tabs') %]</a>
+</div>
+
+<div class="hide_me">
+    <table id='' border="0" width="100%">
+        <tbody id='rdetail_details_tbody'>
+            <tr>
+                <td id='' rowspan='2' valign="top" align="center" style="padding-right:10px;">
+                </td>
+                <td class='rdetail_desc' valign="top" colspan="3">
+                    <table border="0" width="100%">
+                        <tr>
+                            <td valign="top">
+                                <div style="padding-bottom:7px;">
+                                    <strong>[% l("Title") %]:</strong>
+                                </div>
+                            </td>
+                            <td width="1" valign="top" align="right" style="white-space:nowrap;">
+                                <a href="[% ctx.opac_root %]/place_hold[% propagator; propagator.length > 1 ? "&amp;" : ""; %]hold_target=[% ctx.bre_id %]&amp;hold_type=T"><img alt="[% l('Place Hold') %]"
+                                    src="[% ctx.media_prefix %]/images/place_hold.gif" /></a>
+                                <a href="#" id="rd_reviews_and_more" target="_blank"><img
+                                    alt="[% l('Reviews and More') %]" src="[% ctx.media_prefix %]/images/reviews.gif" /></a>
+                                <a href="#" id=""><img alt="[% l('Add to My List') %]"
+                                    src="[% ctx.media_prefix %]/images/add_mylist.gif" /></a>
+                            </td>
+                        </tr>
+                    </table>
+                </td>        
+            </tr>
+            <tr>
+                <td nowrap='nowrap' colspan="3" valign="bottom" style="padding-bottom:16px;">
+                </td>
+            </tr>
+            <tr>
+                <td><div style="height:20px;"></div></td>
+            </tr>
+        </tbody>
+    </table>
+</div> <!-- details_body -->
+
+<!-- ****************** end: rdetail_summary.xml ***************************** -->
diff --git a/Open-ILS/web/templates/default/opac/parts/result/lowhits.tt2 b/Open-ILS/web/templates/default/opac/parts/result/lowhits.tt2
new file mode 100644 (file)
index 0000000..c66b114
--- /dev/null
@@ -0,0 +1,90 @@
+<div id='result_low_hits'>
+    <div id="zero_search_hits">
+        <div>
+            <p>[% l('Sorry, no entries were found for') %]
+                [% IF is_advanced; l('your search'); ELSE %]
+                <q>[% CGI.param('query') | html %]</q>
+                [% END %]
+                <br />
+                <span id="zero_hits_label1" class="hide_me">Did you mean
+                    <strong><a id="spell_check_link" href="javascript:;"></a></strong>?</span>
+            </p>
+            <table cellpadding="0" cellspacing="0" border="0">
+                <tr>
+                    <td valign="top" style="padding-right:10px;">
+                        <span id="zero_hits_label2" class="hide_me">[% l('Other Possibilities:') %]</span>
+                    </td>
+                    <td id="zero_hits_suggestions"></td>
+                </tr>
+            </table>
+        </div>
+        <div style="float:right;width:353px;background:#ccc;padding:10px;margin-top:7px;">
+            [% INCLUDE "default/opac/parts/result/lowhits_purchase.tt2" %]
+            <p>
+                <strong>Keyword Search Tips</strong><br />
+                Change to <strong>Advanced Keyword Search.</strong>
+            </p>
+            <p>
+                <strong>Adjacency</strong><br />
+                Multiple words are not searched together as a phrase. They will
+                be found in various parts of the record. To search for a phrase, enclose your
+                search terms in quotation marks.<br />
+                (example:  <strong>&quot;garcia marquez&quot;</strong>)
+            </p>
+            <p>
+                <strong>Truncation</strong><br />
+                Words may be right-hand truncated using an asterisk. Use a single asterisk *
+                to truncate from 1-5 characters. Use a double asterisk ** for open-ended truncation.<br />
+                (example: <strong>environment* agency</strong>)
+            </p>
+            <p>
+                <strong>Wildcards</strong><br />
+                You may use a question mark to replace a single character anywhere within a word.<br />
+                example: <strong>wom?</strong>)
+            </p>
+        </div>
+    </div>
+    <div class="hide_me">
+        <div style='text-align: center; padding-bottom: 8px;' class="hide_me">
+            <div id='result_low_hits_msg' class='hide_me'>[% l("Few hits were returned for your search.") %]</div>
+            <div id='result_zero_hits_msg' class='hide_me'>[% l("Zero hits were returned for your search.") %]</div>
+        </div>
+
+        <!-- spell checker -->
+        <div id='did_you_mean' class='lowhits_div hide_me'>
+            <span>[% l("Maybe you meant:") %] </span>
+            <!-- <a class='classic_link' id='spell_check_link'> </a> -->
+        </div>
+
+        <div id='low_hits_remove_format' class='lowhits_div hide_me'>
+            <span>[% l("You will find more hits when searching all item formats:") %] </span>
+            <a id='low_hits_remove_format_link' class='classic_link'>[% l("Search again with all formats?") %]</a>
+        </div>
+
+        <div id='low_hits_cross_ref' class='lowhits_div hide_me'>
+            <span>[% l("You may also like to try these related searches:") %]</span>
+            <div style='padding: 5px;'>
+                <a id='low_hits_xref_link' class='classic_link' style='padding-right: 5px;'> </a>
+            </div>
+        </div>
+
+        <div id='low_hits_expand_range' class='lowhits_div hide_me'>
+            <span>[% l("You may also wish to expand your search range to:") %] </span>
+            <a id='low_hits_expand_link' class='classic_link' style='padding-right: 5px;'> </a>
+        </div>
+
+        <div id='low_hits_search_type' class='lowhits_div hide_me'>
+            <span>[% l("You can try searching the same terms by:") %]</span>
+            <a id='low_hits_title_search' class='hide_me classic_link' 
+                style='padding-right: 5px;'>[% l("title") %]</a>
+            <a id='low_hits_author_search' class='hide_me classic_link' 
+                style='padding-right: 5px;'>[% l("author") %]</a>
+            <a id='low_hits_subject_search' class='hide_me classic_link' 
+                style='padding-right: 5px;'>[% l("subject") %]</a>
+            <a id='low_hits_series_search' class='hide_me classic_link' 
+                    style='padding-right: 5px;'>[% l("series") %]</a>
+            <a id='low_hits_keyword_search' class='hide_me classic_link' 
+                style='padding-right: 5px;'>[% l("keyword") %]</a>
+        </div>
+    </div>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/result/lowhits_purchase.tt2 b/Open-ILS/web/templates/default/opac/parts/result/lowhits_purchase.tt2
new file mode 100644 (file)
index 0000000..263269a
--- /dev/null
@@ -0,0 +1,6 @@
+<p>
+    <strong>Still not finding what you are looking for?</strong><br />
+    Request that your library purchase the material you are looking for by making a
+    <a href="javascript:;">Purchase Request</a><br />
+    <strong>Note:</strong> You must be logged in to make a Purchase Request<br />
+</p>
diff --git a/Open-ILS/web/templates/default/opac/parts/result/table.tt2 b/Open-ILS/web/templates/default/opac/parts/result/table.tt2
new file mode 100644 (file)
index 0000000..83da3d8
--- /dev/null
@@ -0,0 +1,242 @@
+[%  PROCESS "default/opac/parts/misc_util.tt2";
+
+    ctx.result_start = 1 + ctx.page_size * page;
+    ctx.result_stop = 1 + ctx.page_size * (page + 1);
+    IF ctx.result_stop > ctx.hit_count; ctx.result_stop = ctx.hit_count; END;
+
+    result_count = ctx.result_start;
+%]
+<div style="height: 10px;"></div>
+[% BLOCK results_count_header %]
+<div class="results_header_nav1">
+    <table cellpadding="0" cellspacing="0" border="0" width="100%">
+        <tr>
+            <td class="h1" width="116">[% l('Search Results') %]</td>
+            <td valign="bottom" nowrap="nowrap" class="result_number">
+                [% |l(ctx.result_start, ctx.result_stop, ctx.hit_count) %]
+                Results <strong>[_1]</strong> - <strong>[_2]</strong> of <strong>[_3]</strong>
+                [% END %]
+                <span style='padding-left: 6px;'>
+                    [% |l(page + 1, page_count) %](page <strong>[_1]</strong> of <strong>[_2]</strong>)[% END %]
+                </span>
+            </td>
+            <td align="right" valign="bottom">
+                <span class='start_end_links_span'>
+                    [%  class = 'search_page_nav_link';
+                        href = '#';
+                        IF page > 0;
+                            href = propagator _ '&amp;page=' _ (page - 1);
+                        ELSE; class = class _ ' invisible'; END;
+                    %]
+                    <a class='[% class %]' href='[% href %]' 
+                        title='[% l("Previous page") %]'><span class="nav_arrow_fix">&#9668;</span> [% l('Previous') %] </a>
+                    <span class='hide_me'
+                        style='padding-left: 11px; padding-right:11px;'>
+                        <span></span>
+                    </span>
+                    [%  class = 'search_page_nav_link';
+                        href = '#';
+                        IF (page + 1) < page_count;
+                            href = propagator _ '&amp;page=' _ (page + 1);
+                        ELSE; class = class _ ' invisible'; END;
+                    %]
+                    <a class='[% class %]' href='[% href %]' 
+                        title='[% l("Next page") %]'> [% l('Next') %] <span class="nav_arrow_fix">&#9658;</span></a>
+                </span>
+            </td>
+        </tr>
+    </table>
+</div>
+[% END %]
+[% ctx.results_count_header = PROCESS results_count_header;
+    ctx.results_count_header %]
+<div id="result_table_div">
+    <table cellpadding="0" cellspacing="0" border="0" width="100%">
+        <tr>
+            <td valign="top" width="1" style="padding-right:20px;">
+                <div style="width:174px;" class="hide_me" id="tehSideBar">SIDEBAR TODO
+                </div>
+            </td>
+            <td class='opac-auto-015' width="1"></td>
+            <td valign="top">
+                <table id="res_table" cellpadding="0" cellspacing="0"
+                    border="0" width="100%" style="margin-top:10px;">
+                    <tbody id="result_table">
+                    [%  FOR rec IN ctx.records;
+                            attrs = {marc_xml => rec.marc_xml};
+                            PROCESS get_marc_attrs args=attrs %]
+                        <tr>
+                            <td class='result_table_row' align='left' width='100%'>
+                                <table cellpadding="0" cellspacing="0" class='result_table_subtable'>
+                                    <tbody class='result_table_subtbody'>
+                                        <tr name='counts_row'>
+                                            <td width="58" valign="top"
+                                                style="font-weight:bold;padding-left:10px;"
+                                                name="results_row_count">[%
+                                                    result_count; result_count = result_count + 1
+                                                %].</td>
+                                            <td class='result_table_pic_header'
+                                                width="78" nowrap="nowrap" valign="top">
+                                                [% ident = attrs.isbn_clean || attrs.upc; IF ident; %]
+                                                <a href="[% ctx.opac_root %]/record/[% rec.id _ propagator %]"><img alt="[% l('Image of item') %]"
+                                                        name='item_jacket' class='result_table_pic' width="55"
+                                                        src='[% ctx.media_prefix %]/opac/extras/ac/jacket/small/[% ident %]' /></a><br />
+                                                [% END %]
+                                            </td>
+                                            <td class='result_table_title_cell'
+                                                name='result_table_title_cell'
+                                                valign="top">
+                                                <div class="bold">
+                                                    <a title="[% attrs.title %]" name='item_title'
+                                                        href="[% ctx.opac_root %]/record/[% rec.id _ propagator %]"
+                                                        class='search_link'>[% attrs.title %]</a>
+                                                </div>
+                                                <div style="font-size:11px;">
+                                                    <div>
+                                                        <em><a title="[% l("Perform an Author Search") %]"
+                                                                name='item_author'
+                                                                href="[% ctx.opac_root %]/results?qtype=author&amp;query=[% 
+                                                                    attrs.author | replace('[,\.:;]', '') | uri %]&amp;loc=[% CGI.param('loc') | uri %]"
+                                                                class='search_link'>[% attrs.author %]</a></em>
+                                                        &nbsp;&nbsp;
+                                                        [% attrs.pubdate %]
+                                                    </div>
+                                                    <table cellpadding="0" cellspacing="0" border="0"
+                                                        class="results_info_table">
+                                                        <tr name='bib_cn_list' class='result_table_title_cell'>
+                                                            <td valign='top'>
+                                                                <strong>[% l('Call number:') %]</strong>
+                                                            </td>
+                                                            <td>[% args.holdings.0 %]</td>
+                                                        </tr>
+                                                        <tr name="results_pub_tr" class="[% attrs.publisher ? '' : 'hide_me' %]">
+                                                            <td valign="top">
+                                                                <strong>[% l('Publisher:') %]</strong>
+                                                            </td>
+                                                            <td>[% attrs.publisher; %]</td>
+                                                        </tr>
+                                                        <tr name="results_isbn_tr" class="[% attrs.isbn ? '' : 'hide_me' %]">
+                                                            <td valign="top">
+                                                                <strong>[% l('ISBN:') %]</strong>
+                                                            </td>
+                                                            <td>[% attrs.isbn %]</td>
+                                                        </tr>
+                                                        <tr name="results_edition_tr" class="[% attrs.edition ? '' : 'hide_me' %]">
+                                                            <td valign="top">
+                                                                <strong>[% l('Edition:') %]</strong>
+                                                            </td>
+                                                            <td>[% attrs.edition %]</td>
+                                                        </tr>
+                                                        <tr name="results_phys_desc_tr" class="[% attrs.phys_desc ? '' : 'hide_me' %]">
+                                                            <td nowrap="nowrap" valign="top">
+                                                                <strong>[% l('Phys. Desc.:') %]</strong>
+                                                            </td>
+                                                            <td>
+                                                                [% args.phys_desc %]
+                                                            </td>
+                                                        </tr>
+                                                    </table>
+                                                    <div>
+                                                        [% l('[_1] of [quant,_2,copy,copies] available',
+                                                            attrs.copy_counts.available, attrs.copy_counts.count) # XXX s/count/nshadow/ ?
+                                                            #rec.copy_counts.available, rec.copy_counts.visible) 
+                                                        %]
+                                                    </div>
+                                                </div>
+                                                <div class="hide_me">
+                                                    <span name='result_table_extra_span' class='hide_me'>
+                                                        <span name='result_table_pub_box'
+                                                            style='padding-left: 10px;'>
+                                                            <span name='result_table_edition_span'
+                                                                style='padding-left: 10px;'></span> |
+                                                            <span name='result_table_pub_span'> </span> |
+                                                            <span name='result_table_phys_span'> </span>
+                                                        </span>
+                                                    </span>
+                                                </div>
+                                            </td>
+
+                                            <td name='result_table_format_cell' class='result_table_format_cell' width="1">
+
+                                                [% IF attrs.format_icon %]
+                                                <img title="[% attrs.format_label %]" alt="[% attrs.format_label %]" src="[% attrs.format_icon %]" />
+                                                [% END %]
+
+                                                <!-- unAPI link -->
+                                                <abbr class="unapi-id" title='tag:[% ctx.hostname %],[% date.format(date.now, '%Y') %]:biblio-record_entry/[% rec.id %]'></abbr>
+
+                                                <!-- Empty span used for creating Google Book Search-->
+                                                <span name="googleBooksLink" class="hide_me">
+                                                    <a style='padding-left: 8px;'
+                                                        class='classic_link hide_me'
+                                                        name="googleBooks-link">[% l("Browse in Google Books Search") %]</a>
+                                                </span>
+
+                                            </td>
+                                            <td nowrap='nowrap' width="1" align="right">
+                                                <div style="width:250px;text-align:left;">
+                                                    <div style="float:right;">
+                                                        <div class="results_aux_utils opac-auto-010"><a
+                                                                href="[% ctx.opac_root %]/place_hold[% propagator; propagator.length > 1 ? "&amp;" : ""; %]hold_target=[% rec.id %]&amp;hold_type=T" 
+                                                                    name="place_hold_link" class="no-dec"><img
+                                                                src="[% ctx.media_prefix %]/images/green_check.png"
+                                                                alt="[% l('Place hold') %]"/><span style="position:relative;top:-3px;left:3px;">[% l('Place Hold') %]</span></a>
+                                                        </div>
+                                                        <div class="results_aux_utils opac-auto-011">
+                                                            [%  operation = ctx.mylist.grep(rec.id).size ? "delete" : "add";
+                                                                label = (operation == "add") ? l("Add to") : l("Remove from"); %]
+                                                            <form action="[% ctx.opac_root %]/mylist/[% operation %]" method="POST">
+                                                                <input type="hidden" name="record" value="[% rec.id %]" />
+                                                            <div style="position:absolute;">
+                                                                <div style="position:relative;top:5px; left: 25px;">
+                                                                    <input type="submit" title="[% l(label _ ' my list') %]" value="[% l(label _ ' my list') %]" class="subtle-button" />
+                                                                </div>
+                                                            </div>
+                                                                <input type="image"
+                                                                alt="[% l(label _ ' my list') %]"
+                                                                src="[% ctx.media_prefix %]/images/clipboard.png" />
+                                                        </form>
+                                                        </div>
+                                                        <!-- <div style="padding-top:7px;" class="results_aux_utils">
+                                                            <a title="Reviews and More" target="_blank" class="no-dec"
+                                                                name="reviews_and_more" href="javascript:;"><img
+                                                                alt="[% l('Reviews and more') %]"
+                                                                src="[% ctx.media_prefix %]/images/starz.png" /> <span
+                                                                    style="position:relative;top:-5px;">[% l('Reviews and More') %]</span></a>
+                                                        </div> -->
+                                                    </div>
+                                                </div>
+                                            </td>
+                                        </tr>
+
+                                        <!-- Placeholder for ChiliFresh Review -->
+                                        <tr class="hide_me" name="chilifreshReview">
+                                            <td></td>
+                                            <td valign="top" colspan="5">
+                                                <div style="position:relative;left:-19px;">
+                                                    <span name="chilifreshReviewLink" class="chili_review"></span>
+                                                    <div name="chilifreshReviewResult" style="display:none"></div>
+                                                </div>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td colspan="5">
+                                                <div style="height:0px;border-top:1px solid #b7b7b7;border-bottom:1px solid #d4d4d4;margin:15px 0px;"></div>
+                                                <!-- <hr class='opac-auto-013' color="#FFCC33" /> -->
+                                            </td>
+                                        </tr>
+                                    </tbody>
+                                </table>
+                            </td>
+                        </tr>
+                    [% END %]
+                    </tbody>
+                </table>
+            </td>
+        </tr>
+    </table>
+</div>
+<div>
+    [% ctx.results_count_header %]
+    <!-- ChiliFresh XXX script TODO -->
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/searchbar.tt2 b/Open-ILS/web/templates/default/opac/parts/searchbar.tt2
new file mode 100644 (file)
index 0000000..a38259f
--- /dev/null
@@ -0,0 +1,77 @@
+[% PROCESS "default/opac/parts/org_selector.tt2" %]
+<div id="search-box">    
+    [% UNLESS took_care_of_form -%]
+    <form action="[% ctx.opac_root %]/results" method="GET">
+    [%- END %]
+    <table cellpadding="0" cellspacing="10" border="0">
+        <tr>
+            <td colspan="3">
+                <span class="search_catalog_lbl">[% l('Search the Catalog') %]</span>
+                <a href="[% ctx.opac_root %]/advanced"
+                    id="home_adv_search_link"><span
+                    class="adv_search_font">[% l('Advanced Search') %]</span></a>
+            </td>
+        </tr>
+        <tr>
+            [% IF is_advanced %]
+            <td colspan="2">
+                <input type="hidden" name="_adv" value="1" />
+            [% ELSE %]
+            <td>
+            [% INCLUDE "default/opac/parts/qtype_selector.tt2" %]
+            </td>
+            [% END %]
+            [% IF ctx.processed_search_query OR NOT is_advanced %]
+            <td>
+                <div id="search_box_wrapper">
+                    <!-- Note: when common browsers support HTML5 placeholder text, we can remove the JS -->
+                    <input type="text" id="search_box" name="query" value="[% is_advanced ? ctx.processed_search_query : CGI.param('query') || l("Search Keyword") | html %]"
+                        [% IF is_advanced %]style="width: 450px"[% END %]
+                        onfocus="if (this.value=='[% l("Search Keyword") %]'){this.value='';this.style.color='#000';}"
+                        onblur="if (this.value==''){this.value='[% l("Search Keyword") %]';this.style.color='#999';}" />
+                </div>
+                <input name='page' type='hidden' value="0" />
+            </td>
+            <td valign="top">
+                <div class="pos-abs">
+                    <div class="opac-auto-143">
+                        <input id='search-submit-go' type="image" alt="[% l('Search') %]" src="[% ctx.media_prefix %]/images/go-btn.png"
+                            onmouseover="this.src='[% ctx.media_prefix %]/images/go-btn-hover.png';"
+                            onmouseout="this.src='[% ctx.media_prefix %]/images/go-btn.png';" 
+                            onclick='setTimeout(function(){$("search-submit-spinner").className=""; $("search-submit-go").className="hidden"}, 2000)'/>
+                        <img id='search-submit-spinner' src='/opac/images/progressbar_green.gif' style='height:16px;width:16px;' class='hidden'/>
+                    </div>
+                </div>
+            </td>
+            [% END %]
+        </tr>
+        [% UNLESS is_advanced %]
+        <tr>
+            <td>
+                [% INCLUDE "default/opac/parts/coded_value_selector.tt2" attr="mattype" none_ok=1 %]
+            </td>
+            <td>
+                <span id='depth_selector_span'>
+                    [% PROCESS build_org_selector name='loc' value=CGI.param('loc') %]
+                </span>
+                <span id='lib_selector_span'>
+                    <a id='lib_selector_link' class='classic_link'
+                        href='#'>[% l("Choose a library to search") %]</a>
+                </span>
+            </td>
+        </tr>
+        [% END %]
+    </table>
+    [% UNLESS took_care_of_form %]</form>[% END %]
+    [% IF is_advanced AND CGI.param('qtype') %]
+    <div class="opac-auto-102">
+        [ <a href="[% ctx.opac_root %]/advanced?[% query_string %]">[%
+            l('Click to Refine Your Original Search')
+        %]</a> ]
+    </div>
+    [% END %]
+    <div id="breadcrumb">
+        <a href="[% ctx.opac_root %]/home">[% l('Catalog Home') %]</a> &gt;
+    </div>
+    <div class="clear-both"></div>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/tips.tt2 b/Open-ILS/web/templates/default/opac/parts/tips.tt2
new file mode 100644 (file)
index 0000000..f4e73ed
--- /dev/null
@@ -0,0 +1,11 @@
+<!-- ****************** tips.xml ***************************** -->
+<div class="hide_me">
+    <div id='tips' class='tips hide_me'>
+        <div class='hide_me'>
+            <span>[% l("Click on a folder icon in the sidebar to access related quick searches") %]</span>
+            <span>[% l("If you don't find what you want try expanding your search using the range selector at the right of the search bar") %]</span>
+        </div>
+        <strong>[% l("Tip:") %]</strong>
+    </div>
+</div>
+<!-- ****************** end: tips.xml ***************************** -->
diff --git a/Open-ILS/web/templates/default/opac/parts/topnav.tt2 b/Open-ILS/web/templates/default/opac/parts/topnav.tt2
new file mode 100644 (file)
index 0000000..5c01e7e
--- /dev/null
@@ -0,0 +1,106 @@
+[% IF !ctx.is_staff %]
+<div id="header">
+    <div class="float-left">
+        [% INCLUDE "default/opac/parts/topnav_logo.tt2" %]
+    </div>
+    <div class="float-right">
+        [% IF !ctx.user %]
+        <div id="your-acct-login">
+            <a href="[% ctx.opac_root %]/myopac/main" id="home_myopac_link"><img
+                alt="[% l('Your Account Log in') %]"
+                src="[% ctx.media_prefix %]/images/login-btn.png"
+                onmouseover="this.src='[% ctx.media_prefix %]/images/login-btn-hover.png';"
+                onmouseout="this.src='[% ctx.media_prefix %]/images/login-btn.png';" /></a>
+        </div>
+        [% ELSE %]
+        <div id="dash_wrapper">
+            <div class="float-right">
+                <table cellpadding="0" cellspacing="0" border="0">
+                    <tr>
+                        <td>
+                            <img src="[% ctx.media_prefix %]/images/dash-corner-left1.png" />
+                        </td>
+                        <td id="dash_corner_mid1a">
+                            <span id="dash_user">
+                                [%  l('[_1] [_2]', ctx.user.first_given_name, ctx.user.family_name) %]
+                            </span>
+                        </td>
+                        <td id="dash_corner_mid1b">
+                            <img src="[% ctx.media_prefix %]/images/dash-divider.jpg" />
+                        </td>
+                        <td id="dash_corner_mid1c">
+
+                            <a href="[% ctx.opac_root %]/myopac/main" class="pos-rel-top4"><img
+                                alt="[% l('My Account') %]"
+                                src="[% ctx.media_prefix %]/images/acct-btn.png"
+                                onmouseover="this.src='[% ctx.media_prefix %]/images/acct-btn-hover.png';"
+                                onmouseout="this.src='[% ctx.media_prefix %]/images/acct-btn.png';" /></a>
+
+                            <a href="[% ctx.opac_root %]/logout" class="pos-rel-top4"
+                                id="logout_link"><img
+                                alt="[% l('Logout') %]"
+                                src="[% ctx.media_prefix %]/images/logout-btn.png"
+                                onmouseover="this.src='[% ctx.media_prefix %]/images/logout-btn-hover.png';"
+                                onmouseout="this.src='[% ctx.media_prefix %]/images/logout-btn.png';" /></a>
+                        </td>
+                        <td>
+                            <img src="[% ctx.media_prefix %]/images/dash-corner-right1.png" />
+                        </td>
+                    </tr>
+                </table>
+            </div>
+            <div id="dashboard">
+                <div class="pos-abs">
+                    <div class="pos-rel-top4">
+                        <table cellpadding="0" cellspacing="0" border="0">
+                            <tr>
+                                <td>
+                                    <img src="[% ctx.media_prefix %]/images/dash-corner-left2.png" />
+                                </td>
+                                <td id="dash_corner_mid2a">
+                                    <div id="dash_number_row">
+                                        <div class="pos-abs">
+                                            <div class="dash-pos-out">
+                                                <div class="dash-align-out">
+                                                    <a class="dash-link" href="[% ctx.opac_root %]/myopac/circs"><span id="dash_checked">[% ctx.user_stats.checkouts.total_out %]</span> [% l("Checked Out") %]</a>
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <div class="pos-abs">
+                                            <div class="dash-pos-holds">
+                                                <div class="dash-align-holds">
+                                                    <a class="dash-link" href="[% ctx.opac_root %]/myopac/holds"><span id="dash_holds">[% ctx.user_stats.holds.total %]</span> [% l("On Hold") %]</a>
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <div class="pos-abs">
+                                            <div class="dash-pos-pickup">
+                                                <div class="dash-align-pickup">
+                                                    <a class="dash-link" href="[% ctx.opac_root %]/myopac/holds?available=1"><span id="dash_pickup">[% ctx.user_stats.holds.ready %]</span> [% l("Ready for Pickup") %]</a>
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <div class="pos-abs">
+                                            <div class="dash-pos-fines">
+                                                <div class="dash-align-fines">
+                                                    <a class="dash-link" href="[% ctx.opac_root %]/myopac/main"><span id="dash_fines">[% money(ctx.user_stats.fines.balance_owed) %]</span> [% l("Fines") %]</a>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </td>
+                                <td>
+                                    <img src="[% ctx.media_prefix %]/images/dash-corner-right2.png" />
+                                </td>
+                            </tr>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+        [% END %]
+    </div>
+    <div class="common-no-pad"></div>
+</div>
+[% END %]
+[% INCLUDE "default/opac/parts/topnav_links.tt2" %]
diff --git a/Open-ILS/web/templates/default/opac/parts/topnav_links.tt2 b/Open-ILS/web/templates/default/opac/parts/topnav_links.tt2
new file mode 100644 (file)
index 0000000..e6f4169
--- /dev/null
@@ -0,0 +1,11 @@
+<div id="gold-links-holder">
+    <div id="gold-links">
+        <div id="header-links">
+            <a href="http://example.com">[% l('Link 1') %]</a>
+            <a href="http://example.com">[% l('Link 2') %]</a>
+            <a href="http://example.com">[% l('Link 3') %]</a>
+            <a href="http://example.com">[% l('Link 4') %]</a>
+            <a href="http://example.com">[% l('Link 5') %]</a>
+        </div>
+    </div>
+</div>
diff --git a/Open-ILS/web/templates/default/opac/parts/topnav_logo.tt2 b/Open-ILS/web/templates/default/opac/parts/topnav_logo.tt2
new file mode 100644 (file)
index 0000000..7e479f9
--- /dev/null
@@ -0,0 +1,2 @@
+        <a href="http://evergreen-ils.org"><img alt="[% l('Evergreen Logo') %]" 
+            src="[% ctx.media_prefix %]/opac/images/small_logo.jpg" /></a>
diff --git a/Open-ILS/web/templates/default/opac/place_hold.tt2 b/Open-ILS/web/templates/default/opac/place_hold.tt2
new file mode 100644 (file)
index 0000000..3e6d2bd
--- /dev/null
@@ -0,0 +1,16 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/base.tt2";
+    INCLUDE "default/opac/parts/topnav.tt2";
+    ctx.page_title = l("Place Hold") %]
+    <div id="search-wrapper">
+        [% INCLUDE "default/opac/parts/printnav.tt2" %]
+        [% INCLUDE "default/opac/parts/searchbar.tt2" %]
+    </div>
+    <div id="content-wrapper">
+        <div id="main-content">
+            <div class="common-full-pad"></div>        
+            [% INCLUDE "default/opac/parts/place_hold.tt2" %]
+            <div class="common-full-pad"></div>        
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/record.tt2 b/Open-ILS/web/templates/default/opac/record.tt2
new file mode 100644 (file)
index 0000000..0149bf1
--- /dev/null
@@ -0,0 +1,15 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    WRAPPER "default/opac/parts/base.tt2";
+    INCLUDE "default/opac/parts/topnav.tt2";
+    ctx.page_title = l("Record Detail") %]
+    <div id="search-wrapper">
+        [% INCLUDE "default/opac/parts/printnav.tt2" %]
+        [% INCLUDE "default/opac/parts/searchbar.tt2" %]
+    </div>
+    <div id="content-wrapper" class="content-wrapper-record-page">
+        <div id="main-content">
+            [% INCLUDE "default/opac/parts/record/body.tt2" %]
+            <div class="common-full-pad"></div>        
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates/default/opac/results.tt2 b/Open-ILS/web/templates/default/opac/results.tt2
new file mode 100644 (file)
index 0000000..0fb4c31
--- /dev/null
@@ -0,0 +1,74 @@
+[%  PROCESS "default/opac/parts/header.tt2";
+    USE POSIX;
+
+    WRAPPER "default/opac/parts/base.tt2";
+    INCLUDE "default/opac/parts/topnav.tt2";
+    ctx.page_title = l("Search Results");
+
+    page = CGI.param('page') || 0;
+    page_count = POSIX.ceil(ctx.hit_count / ctx.page_size);
+%]
+    <form action="[% ctx.opac_root %]/results" method="GET">
+    <div id="search-wrapper">
+        [% INCLUDE "default/opac/parts/printnav.tt2" %]
+        [% INCLUDE "default/opac/parts/searchbar.tt2" took_care_of_form=1 %]
+    </div>
+    <div class="almost-content-wrapper">
+        <div id="results_header_bar">
+            <div id="results_header_inner">
+                <div class="results_header_btns">
+                    <a href="[% ctx.opac_root %]/home"><img alt="[% l('Another Search') %]"
+                        src="[% ctx.media_prefix %]/images/another_search.png"
+                        onmouseover="this.src='[% ctx.media_prefix %]/images/another_search_hover.png';"
+                        onmouseout="this.src='[% ctx.media_prefix %]/images/another_search.png';" /></a>
+                </div>
+                <div class="results_header_btns">
+                    <a href="[% ctx.opac_root %]/advanced"><img alt="[% l('Advanced Search') %]"
+                        src="[% ctx.media_prefix %]/images/adv_search.png"
+                        onmouseover="this.src='[% ctx.media_prefix %]/images/adv_search_hover.png';"
+                        onmouseout="this.src='[% ctx.media_prefix %]/images/adv_search.png';" /></a>
+                </div>
+                [% IF ctx.mylist.size %]
+                <div class="results_header_btns cached_list_div">
+                    <a href="[% ctx.opac_root; ctx.user ? '/myopac/lists' : '/mylist' %]"><img
+                        alt="View My List"
+                        src="[% ctx.media_prefix %]/images/view_my_list.png"
+                        onmouseover="this.src='[% ctx.media_prefix %]/images/view_my_list_hover.png';"
+                        onmouseout="this.src='[% ctx.media_prefix %]/images/view_my_list.png';" /></a>
+                </div>
+                [% END %]
+                <div class="results_header_div"></div>
+                [% UNLESS is_advanced %]
+                    <div class="results_header_lbl">Sort by</div>
+                    [% INCLUDE "default/opac/parts/filtersort.tt2" value=CGI.param('sort') %]
+                    <div class="results_header_div"></div>
+                    <!-- XXX still needed?<div class="results_header_lbl">View</div>
+                    <select class="results_header_sel">
+                        <option>Simple</option>
+                        <option>Detailed</option>
+                    </select>
+                    <div class="results_header_div"></div> -->
+                    <input type="checkbox" id="limit_to_available"
+                        name="modifier" value="available"
+                        [% CGI.param('modifier').grep('available').size
+                            ? ' checked="checked"' : '' %] />
+                    <label for="limit_to_available" class="results_header_lbl">
+                        [% l('Limit to available items') %]
+                    </label>
+                [% END %]
+                <div class="clear-both"></div>
+            </div>
+        </div>
+    </div>
+    </form>
+    <div id="content-wrapper">
+        <div id="main-content">
+            <div id="tehResultsPage">
+                [% path = "default/opac/parts/result/" _
+                    (ctx.records.size ? "table.tt2" : "lowhits.tt2");
+                INCLUDE $path %]
+            </div>
+            <div class="common-full-pad"></div>    
+        </div>
+    </div>
+[% END %]
diff --git a/Open-ILS/web/templates_kcls/default/opac/myopac/main_refund_policy.tt2 b/Open-ILS/web/templates_kcls/default/opac/myopac/main_refund_policy.tt2
new file mode 100644 (file)
index 0000000..9ad8bc0
--- /dev/null
@@ -0,0 +1,24 @@
+<tr>
+    <td colspan="3">
+        <br />
+        Important! You must have a printed receipt to be
+        eligible for a refund on lost items (regulations allow
+        for no exceptions).
+        <br />
+        <strong>
+            To ensure your necessary receipt information is
+            not lost, enter your email address above and a
+            receipt will be emailed to you. Otherwise, make
+            certain you have a printed receipt in hand before
+            closing the payment receipt screen.
+        </strong>
+        <br />
+        Refunds are not available for parts and pieces, overdue
+        fines, or items that do not display a specific title in
+        My Account. For a full list of refundable and
+        non-refundable items, visit
+        <a href="http://www.kcls.org/usingthelibrary/borrowing/refundable.cfm">http://www.kcls.org/usingthelibrary/borrowing/refundable.cfm</a><br /><br />
+        This site uses VeriSign SSL encryption to ensure your
+        privacy.
+    </td>
+</tr>
diff --git a/Open-ILS/web/templates_kcls/default/opac/parts/footer.tt2 b/Open-ILS/web/templates_kcls/default/opac/parts/footer.tt2
new file mode 100644 (file)
index 0000000..9ab3ace
--- /dev/null
@@ -0,0 +1,10 @@
+<div id="footer">
+    <a href="http://www.kcls.org/usingthelibrary/request/">[% l('Request a Purchase') %]</a> &nbsp;|&nbsp;
+    <a href="http://www.kcls.org/usingthelibrary/request/">[% l('Interlibrary Loan') %]</a> &nbsp;|&nbsp;
+    <a href="http://www.kcls.org/about/contact/">[% l('Contact Us') %]</a> &nbsp;|&nbsp;
+    <a href="http://www.kcls.org/usingthelibrary/catalog_help/">[% l('Site Help') %]</a> &nbsp;|&nbsp;
+    <a href="http://www.kcls.org/usingthelibrary/policies/privacy.cfm">[% l('Privacy Statement') %]</a> &nbsp;|&nbsp;
+    <a href="http://www.kcls.org/about/support/">[% l('Support KCLS') %]</a> &nbsp;|&nbsp;
+    <a href="http://www.kcls.org/employment/">[% l('Employment') %]</a> 
+</div>
+
diff --git a/Open-ILS/web/templates_kcls/default/opac/parts/homesearch.tt2 b/Open-ILS/web/templates_kcls/default/opac/parts/homesearch.tt2
new file mode 100644 (file)
index 0000000..2021f16
--- /dev/null
@@ -0,0 +1,64 @@
+<div style='width:664px;height:35px;background:#FFFFFF;'>
+    <strong><center></center></strong>
+</div>
+<div id='hp-banner'>
+    <a href='http://www.kcls.org/newcatalog/'><img
+        src='[% ctx.media_prefix %]/images/golive.jpg'
+        alt='new catalog' title='New Catalog Information' /></a>
+</div>
+<div id='hp-buttons'>
+    <div class="float-left">
+        <img src='[% ctx.media_prefix %]/images/hp-links-left.jpg' />
+    </div>
+    <div class="float-left">
+           <div id='homesearch_thing'>
+               <table cellpadding='0' cellspacing='5' border='0' id='hp-ql-table'>
+                <tr>
+                    <td colspan='4'>
+                        <span class="opac-auto-029">
+                            [% l("Browse for") %]:
+                        </span>
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href='http://www.kcls.org/booksandreading/'>books</a>
+                    </td>
+                    <td>
+                        <a href='http://www.kcls.org/movies/movies_browse.cfm'>movies</a>
+                    </td>
+                    <td>
+                        <a href='http://www.kcls.org/ecollection/'>downloads</a>
+                    </td>
+                    <td>
+                        <a href='http://www.kcls.org/websites/'>websites</a>
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href='http://www.kcls.org/music/'>music</a>
+                    </td>
+                    <td>
+                        <a href='http://www.kcls.org/databases/subject_categories.cfm#17'>magazines</a>
+                    </td>
+                    <td>
+                        <a href='http://www.kcls.org/databases/'>databases</a>
+                    </td>
+                    <td>
+                        <a href='http://www.kcls.org/answers/'>answers</a>
+                    </td>
+                </tr>
+               </table>
+           </div>
+           <div id='hp-ql-bottom'>
+            <a href='http://www.kcls.org/locations'>Locations:
+                Find a Library Near You!
+                <img src='[% ctx.media_prefix %]/images/arrow-right.png' /></a>
+
+           </div>
+    </div>
+    <div class="float-left">
+        <img src='[% ctx.media_prefix %]/images/hp-links-right.jpg' />
+    </div>
+    <div class="clear-both"></div>
+</div>
diff --git a/Open-ILS/web/templates_kcls/default/opac/parts/login/help.tt2 b/Open-ILS/web/templates_kcls/default/opac/parts/login/help.tt2
new file mode 100644 (file)
index 0000000..a6d7ebb
--- /dev/null
@@ -0,0 +1,12 @@
+<td class="login_boxes right_brain" align="center" valign="top" width="291">
+
+    <a href="http://www.kcls.org/about/contact/"><img 
+        src="[% ctx.media_prefix %]/images/questions.png" alt="[% l('Questions?') %]" style="margin-top:29px;" /></a>
+
+    <div style="width:182px;color:black;padding:5px 25px;">
+        [% l('Visit our FAQs section for answers to common questions about how to use your account.') %]
+    </div>
+
+    <a href="http://www.kcls.org/usingthelibrary/catalog_help/index.cfm#FAQs"><img
+        alt="[% l('FAQs') %]" src="[% ctx.media_prefix %]/images/faqs-btn.png" style="margin-top:13px;" /></a>
+</td>
diff --git a/Open-ILS/web/templates_kcls/default/opac/parts/myopac/prefs_hints.tt2 b/Open-ILS/web/templates_kcls/default/opac/parts/myopac/prefs_hints.tt2
new file mode 100644 (file)
index 0000000..bb7c642
--- /dev/null
@@ -0,0 +1,4 @@
+<a href=
+        "http://www.kcls.org/usingthelibrary/catalog_help/library_elf.cfm"><u>Try
+        Library Elf-to manage library materials!</u></a>
+
diff --git a/Open-ILS/web/templates_kcls/default/opac/parts/printnav.tt2 b/Open-ILS/web/templates_kcls/default/opac/parts/printnav.tt2
new file mode 100644 (file)
index 0000000..13a8f66
--- /dev/null
@@ -0,0 +1,25 @@
+<div class="big-block">
+    <div class="float-right">
+        <div class="pos-rel">
+            <img src="[% ctx.media_prefix %]/images/utils-corner-left.png" class="float-left" />
+            <div class="left-corner"> 
+                <a href="javascript:history.go(-1)"
+                    id="util_back_btn"><img alt="[% l('Back') %]"
+                    src="[% ctx.media_prefix %]/images/tool_back.png" /></a>
+                <a href="[% ctx.opac_root %]/home"
+                    id="util_home_btn"><img alt="[% l('Homepage') %]"
+                    src="[% ctx.media_prefix %]/images/tool_home.png" /></a>
+                <a href="javascript:window.print();"
+                    id="util_print_btn"><img alt="[% l('Print Page') %]"
+                    src="[% ctx.media_prefix %]/images/tool_print.png" /></a>
+                <a href="http://www.kcls.org/usingthelibrary/catalog_help/index.cfm"
+                    id="util_help_btn"><img alt="[% l('Help') %]"
+                    src="[% ctx.media_prefix %]/images/tool_help.png" /></a>
+                <a href="javascript:history.go(+1)"
+                    id="util_forw_btn"><img alt="[% l('Forward') %]"
+                    src="[% ctx.media_prefix %]/images/tool_forward.png" /></a>
+            </div>
+            <img src="[% ctx.media_prefix %]/images/utils-corner-right.png" class="float-left" />
+        </div>
+    </div>
+</div>
diff --git a/Open-ILS/web/templates_kcls/default/opac/parts/result/lowhits_purchase.tt2 b/Open-ILS/web/templates_kcls/default/opac/parts/result/lowhits_purchase.tt2
new file mode 100644 (file)
index 0000000..a41f658
--- /dev/null
@@ -0,0 +1,6 @@
+<p>
+    <strong>Still not finding what you are looking for?</strong><br />
+    Request that KCLS purchase the material you are looking for by making a
+    <a href="javascript:;">Purchase Request</a><br />
+    <strong>Note:</strong> You must be logged in to make a Purchase Request<br />
+</p>
diff --git a/Open-ILS/web/templates_kcls/default/opac/parts/topnav_links.tt2 b/Open-ILS/web/templates_kcls/default/opac/parts/topnav_links.tt2
new file mode 100644 (file)
index 0000000..6ea4b4d
--- /dev/null
@@ -0,0 +1,13 @@
+<div id="gold-links-holder">
+    <div id="gold-links">
+        <div id="header-links">
+            <a href="http://www.kcls.org/usingthelibrary/index.cfm">Using the Library</a>
+            <a href="http://www.kcls.org/booksandreading/">Books &amp; Reading</a>
+            <a href="http://www.kcls.org/research/index.cfm">Research &amp; Homework</a>
+            <a href="http://www.kcls.org/programs/">Programs &amp; Classes</a>
+            <a href="http://www.kcls.org/events/">Events</a>
+            <a href="/opac/extras/mobile/">Mobile Catalog</a>
+            <a href="http://www.kcls.org/about/">About KCLS</a>
+        </div>
+    </div>
+</div>
diff --git a/Open-ILS/web/templates_kcls/default/opac/parts/topnav_logo.tt2 b/Open-ILS/web/templates_kcls/default/opac/parts/topnav_logo.tt2
new file mode 100644 (file)
index 0000000..f9d4320
--- /dev/null
@@ -0,0 +1,2 @@
+        <a href="http://www.kcls.org"><img alt="[% l('KCLS Logo') %]" 
+            src="[% ctx.media_prefix %]/images/KCLS_logo_horiz.gif" /></a>