From 3f642996f51ac87c55b152111c25c020c1a5f869 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 29 Oct 2014 17:05:52 -0400 Subject: [PATCH] Search Templates (kmig 123) Cross-port: 5f1f13e --- .../conify/global/config/search_templates.tt2 | 286 +++++++++++++ .../templates_kcls/opac/parts/advanced/search.tt2 | 399 +++++++----------- .../var/templates_kcls/opac/parts/config.tt2 | 105 ++++- .../var/templates_kcls/opac/parts/misc_util.tt2 | 454 +++++++++++++++++---- .../kcls/conify/global/config/search_templates.js | 427 +++++++++++++++++++ Open-ILS/web/opac/locale/en-US/lang.dtd | 1 + .../staff_client/chrome/content/OpenILS/data.js | 34 +- .../xul/staff_client/chrome/content/main/menu.js | 6 + .../chrome/content/main/menu_frame_menus.xul | 2 + .../chrome/locale/en-US/offline.properties | 1 + 10 files changed, 1383 insertions(+), 332 deletions(-) create mode 100644 KCLS/openils/var/templates_kcls/conify/global/config/search_templates.tt2 create mode 100644 Open-ILS/web/js/ui/kcls/conify/global/config/search_templates.js diff --git a/KCLS/openils/var/templates_kcls/conify/global/config/search_templates.tt2 b/KCLS/openils/var/templates_kcls/conify/global/config/search_templates.tt2 new file mode 100644 index 0000000000..a04847cc6e --- /dev/null +++ b/KCLS/openils/var/templates_kcls/conify/global/config/search_templates.tt2 @@ -0,0 +1,286 @@ +[% WRAPPER base.tt2 %] +[% INCLUDE 'opac/parts/js.tt2' %] +[% + PROCESS "opac/parts/config.tt2"; +%] + + + + + + + + +
+

[% l('Search Settings') %]

+
+ +
+

[% l('Current Template') %]

+ +
+
+
+
+ + [% l('Template Name') %] +
+ + + + + + + + +
+ + + +
+ +
+
+
+ + + + [% INCLUDE "opac/parts/advanced/global_row.tt2" %] + + +
+ +
+ + +[% + in_row = 0; + FOR adv_chunk IN search.adv_config; + NEXT IF adv_chunk.adv_hide; + IF in_row == 0; + in_row = 1; %] + +[% + END; %] + [% IF adv_chunk.adv_attr.size || adv_chunk.adv_filter.size; %] + + [% END; %] + [% IF adv_chunk.adv_break; + in_row = 0; %] + + [% END; %] + [% END; %] + + + + + + + + + + + + + +
+ [% adv_chunk.adv_label %] +
+ +
+ [% l('Search Library') %] +
+ +
+ [% l('Publication Date') %] +
+ +
+ [% l('Search Results') %] +
+ +
+ [% l('Result View') %] +
+ +
+ + [% l('Limit to Available') %] +
+ +
+ +
+ +
+ + + + + +[% END %] diff --git a/KCLS/openils/var/templates_kcls/opac/parts/advanced/search.tt2 b/KCLS/openils/var/templates_kcls/opac/parts/advanced/search.tt2 index 13155df424..17ae8188ad 100644 --- a/KCLS/openils/var/templates_kcls/opac/parts/advanced/search.tt2 +++ b/KCLS/openils/var/templates_kcls/opac/parts/advanced/search.tt2 @@ -1,251 +1,168 @@ -
- - - - - - - + + + + +[% IF ctx.is_staff && search.allow_templates == 'true' %] + + + + + + + +[% END %] \ No newline at end of file diff --git a/KCLS/openils/var/templates_kcls/opac/parts/config.tt2 b/KCLS/openils/var/templates_kcls/opac/parts/config.tt2 index 696a99d794..caff29486b 100644 --- a/KCLS/openils/var/templates_kcls/opac/parts/config.tt2 +++ b/KCLS/openils/var/templates_kcls/opac/parts/config.tt2 @@ -6,6 +6,15 @@ ############################################################################## ############################################################################## +# Holds blocking +############################################################################## +# Prevent the "Place hold" link from being displayed if a copy is available. +# This is not perfect, given the umpteen different types of holds that are +# possible, but addresses the major use case for libraries that don't want +# to fetch copies from the shelves. +ctx.holds_block.enabled = 'false'; + +############################################################################## # RefWorks configuration ############################################################################## # RefWorks is a Web-based citation manager @@ -47,6 +56,22 @@ google_analytics.code = 'UA-9999999-99'; reset_password = 'true'; ############################################################################## +# Hide various options from user preferences that you might not want to expose +# if you rely on centralized authentication via open-ils.auth_proxy, like LDAP +# +# Username changes can be disabled by the opac.lock_usernames OU setting. +############################################################################## +disable_password_change = 'false'; +disable_email_change = 'false'; + +############################################################################## +# Some libraries do not do notifications by phone; if not true, then this +# hides the user preference for phone notifications as well as the phone +# notification portion of the hold dialogue +############################################################################## +allow_phone_notifications = 'true'; + +############################################################################## # Misc. UI Settings ############################################################################## @@ -56,16 +81,90 @@ reset_password = 'true'; # Options are "small", "medium", and "large" record.summary.jacket_size = 'medium'; + ############################################################################## # Define the order in which facets are displayed. Only facets listed here # will be displayed. To show all facets sorted by name, comment out this # setting. # facet.display = [] # show no facets facet.display = [ - {facet_class => 'subject', facet_order => ['complete']} - {facet_class => 'series', facet_order => ['seriestitle']}, - {facet_class => 'identifier', facet_order => ['mattype']}, + {facet_class => 'author', facet_order => ['personal', 'corporate']}, + {facet_class => 'subject', facet_order => ['topic']}, + {facet_class => 'series', facet_order => ['seriestitle']}, + {facet_class => 'subject', facet_order => ['name', 'geographic']} ]; +facet.default_display_count = 5; + +################## +## KCLS settings from 2.2 +#facet.display = [ +# {facet_class => 'subject', facet_order => ['complete']} +# {facet_class => 'series', facet_order => ['seriestitle']}, +# {facet_class => 'identifier', facet_order => ['mattype']}, +#]; +################## + +############################################################################## +# Define the advanced search limiters and labels. +# adv_label is the (translated) label for the limiter +# adv_attr is an array of possible limiters, the first one that has any +# values will be used +# adv_filter is the same as adv_attr, but for search filter groups +# adv_break will end the current row. If specified with a label/attr it +# will do so *after* that limiter. +# adv_special will drop in a special entry: +# lib_selector will put the search library box (with limit to available) +# pub_year will put the publication year box +# sort_selector will put the sort results selector + +search.adv_config = [ + {adv_label => l("Item Type"), adv_attr => ["mattype", "item_type"]}, +# {adv_label => l("Item Form"), adv_attr => "item_form"}, + {adv_label => l("Language"), adv_attr => "item_lang"}, + {adv_label => l("Audience"), adv_attr => ["audience_group", "audience"]}, + {adv_label => l("Sort Results"), adv_special => "sort_selector", adv_break => 1}, +# {adv_label => l("Video Format"), adv_attr => "vr_format"}, +# {adv_label => l("Bib Level"), adv_attr => "bib_level"}, +# {adv_label => l("Literary Form"), adv_attr => "lit_form", adv_break => 1}, + {adv_label => l("Search Library"), adv_special => "lib_selector"}, + {adv_label => l("Publication Year"), adv_special => "pub_year"}, +]; + +############################################################################## +# For each search box the default "query type" value can be specified here +# This is the actual backend value, not the label +# Also note that including more than the row count entries won't add rows +# The first entry should be used as a default for "basic" search as well + +search.default_qtypes = ['keyword','title','author']; + +############################################################################## +# Basic Search Box definition +# This allows selection of what, exactly, basic search uses for a selection +# box. Previously it was hardcoded to use an attr box of mattype or item_type. +# +# type can be "attr" or "filter" +# group is the attr or filter entries you want to check for +# none_label is the label for the default nothing selected entry. + +search.basic_config = { + type => 'attr', + group => ['mattype','item_type'], + none_label => l("All Formats"), +}; + +############################################################################## +# Show Google Book Previews +# Set to 1 or 'true' to enable +ctx.google_books_preview = 0; + +############################################################################## +# This will allow the display and use of a Search Template dropdown that +# staff may use to select often used searches. Upon selection of a Template, the +# Advanced Search page's Global Rows and Search Filters will populate according +# to the Template. Templates are configurable at +# Admin->WorkStation Administraion->Search Templates +search.allow_templates = 'true'; %] diff --git a/KCLS/openils/var/templates_kcls/opac/parts/misc_util.tt2 b/KCLS/openils/var/templates_kcls/opac/parts/misc_util.tt2 index 49a17141c7..a1dbb94f0a 100644 --- a/KCLS/openils/var/templates_kcls/opac/parts/misc_util.tt2 +++ b/KCLS/openils/var/templates_kcls/opac/parts/misc_util.tt2 @@ -1,9 +1,96 @@ [% + # Support multiscript records via alternate graphic 880 fields + # get_graphic_880s(target_field='100') + # See "Model A" in http://www.loc.gov/marc/bibliographic/ecbdmulti.html + # and $6 description in http://www.loc.gov/marc/bibliographic/ecbdcntf.html + MACRO get_graphic_880s BLOCK; + FOR node IN xml.findnodes('//*[@tag="' _ target_field _ '"]'); + raw_vals = []; + core_val = ''; + FOR subnode IN node.findnodes('./*[not(contains("w 0 4 5 6 8 9", @code))]'); + raw_vals.push(subnode.textContent()); + END; + core_val = raw_vals.join(" "); + raw_vals = []; + + linked_fields = []; + FOR sub IN node.findnodes('./*[@code="6"]'); + linked_fields.push(sub.textContent); + END; + graphics = []; + get_linked_880s; + graphic_880s.push({ + primary => {"occur" => occurrence, "value" => core_val}, + graphic => graphics + }); + END; + END; + + MACRO get_linked_880s BLOCK; + FOR link_field IN linked_fields; + target = target_field _ link_field.substr(3); + # Get the linked 880 value + raw_val = ''; + dir = ''; + occurrence = ''; + script = ''; + FOR node IN xml.findnodes('//*[@tag="880"]'); + # Operate only on the target linked fields + FOR linknode IN node.findnodes('./*[@code="6"]'); + lf = linknode.textContent(); + IF lf.substr(0, target.length) == target; + occurrence = lf.substr(4, 2); + rawscript = lf.substr(7, 2); + SWITCH rawscript; + CASE '(3'; + script = 'Arabic'; + CASE '(B'; + script = 'Latin'; + CASE '$1'; + script = 'CJK'; + CASE '(N'; + script = 'Cyrillic'; + CASE '(S'; + script = 'Greek'; + CASE '(2'; + script = 'Hebrew'; + END; + + rawdir = lf.substr(9, 1); + SWITCH rawdir; + CASE 'r'; + dir = 'rtl'; + END; + + raw_vals = []; + FOR subnode IN node.findnodes('./*[not(contains("w 0 5 6 8 9", @code))]'); + raw_vals.push(subnode.textContent()); + END; + raw_val = raw_vals.join(" "); + END; + END; + END; + graphics.push({ + occur => occurrence, + value => raw_val, + script => script, + dir => dir + }); + END; + END; + # Extract MARC fields from XML # get_marc_attrs( { marc_xml => doc } ) BLOCK get_marc_attrs; xml = args.marc_xml; - + + # Map item types to schema.org types; impedance mismatch :( + args.schema.itemtype = {}; + schema_typemap = {}; + schema_typemap.a = 'http://schema.org/Book'; + schema_typemap.e = 'http://schema.org/Map'; + schema_typemap.j = 'http://schema.org/MusicAlbum'; + args.isbns = []; FOR isbn IN xml.findnodes('//*[@tag="020"]/*[@code="a"]'); args.isbns.push(isbn.textContent); @@ -14,89 +101,140 @@ args.upcs.push(upc.textContent); END; args.upc = args.upcs.0; # use first UPC as the default - args.issn = xml.findnodes('//*[@tag="022"]/*[@code="a"]').textContent; - - titresults = xml.findnodes('//*[@tag="245"]/*[@code="a" or @code="b" or @code="n" or @code="p"]'); + + args.issns = []; + FOR sub IN xml.findnodes('//*[@tag="022"]/*[@code="a"]'); + args.issns.push(sub.textContent); + END; + args.issn = (args.issns.size) ? args.issn.0 : ''; + + graphic_880s = []; + get_graphic_880s(target_field='100'); + get_graphic_880s(target_field='110'); + get_graphic_880s(target_field='111'); + args.graphic_authors = graphic_880s; + args.authors = []; + FOR author IN args.graphic_authors; + args.authors.push(author.primary.value); + END; + args.author = (args.authors.size) ? args.authors.0 : ''; + + # Include subfields 'abnp' to generate a more comprehensive title display in search results + titresults = xml.findnodes('//*[@tag="245"]/*[@code="a" or @code="b" or @code="n" or @code="p"]'); titresults_content = []; - FOR sub IN titresults; - titresults_content.push(sub.textContent); - END; - attrs.title = titresults_content.join(" "); - attrs.title = attrs.title | replace('[:;/,]$', ''); - - args.title_extended = ''; - FOR node IN xml.findnodes('//*[@tag="245"]/*'); - args.title_extended = args.title_extended _ ' ' _ node.textContent; - END; - - args.author = xml.findnodes('//*[@tag="100"]/*[@code="a"]').textContent || xml.findnodes('//*[@tag="110"]/*[@code="a"]').textContent || ''; - - args.publishers = xml.findnodes('//*[@tag="260"]/*[@code="b"]') - || xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="b"]') - || ''; - args.publishers_content = []; - FOR sub IN args.publishers; - args.publishers_content.push(sub.textContent); - END; - args.publisher = (args.publishers_content.size) ? args.publishers_content.0 : ''; - - args.pubdates = xml.findnodes('//*[@tag="260"]/*[@code="c"]'); - args.pubdates_content = []; - IF args.pubdates; - FOR sub IN args.pubdates; - args.pubdates_content.push(sub.textContent); - END; - ELSE; - args.pubdates = xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="c"]'); - args.pubdates_content = []; - FOR sub IN args.pubdates; - args.pubdates_content.push(sub.textContent); - END; - IF args.pubdates; - args.copyright = xml.findnodes('//*[@tag="264" and @ind2="4"]/*[@code="c"]').textContent || ''; - END; - END; - args.pubdate = (args.pubdates_content.size) ? args.pubdates_content.0 : ''; - - 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( + FOR sub IN titresults; titresults_content.push(sub.textContent); END; + args.title = titresults_content.join(" "); + # Avoid ugly trailing syntax on brief titles + args.title = args.title | replace('[:;/]$', ''); + + graphic_880s = []; + get_graphic_880s(target_field='245'); + args.graphic_titles = graphic_880s; + args.titles = []; + FOR title IN args.graphic_titles; + args.titles.push(title.primary.value); + END; + args.title_extended = (args.titles.size) ? args.titles.0 : ''; + + args.pubplaces = []; + pubplace_hunt = xml.findnodes('//*[@tag="260"]/*[@code="a"]') || + xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="a"]'); + FOR sub IN pubplace_hunt; + args.pubplaces.push(sub.textContent); + END; + args.pubplace = (args.pubplaces.size) ? args.pubplaces.0 : ''; + + args.publishers = []; + publishers_hunt = xml.findnodes('//*[@tag="260"]/*[@code="b"]') || + xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="b"]'); + FOR sub IN publishers_hunt; + args.publishers.push(sub.textContent); + END; + args.publisher = (args.publishers.size) ? args.publishers.0 : ''; + + args.pubdates = []; + pubdates_hunt = xml.findnodes('//*[@tag="260"]/*[@code="c"]') || + xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="c"]'); + FOR sub IN pubdates_hunt; + args.pubdates.push(sub.textContent); + END; + args.pubdate = (args.pubdates.size) ? args.pubdates.0 : ''; + + # Full publisher info + args.pubinfo = "$args.pubplace $args.publisher $args.pubdate"; + + graphic_880s = []; + get_graphic_880s(target_field='260'); + args.graphic_pubinfos = graphic_880s; + args.pubinfos = []; + FOR pubinfo IN args.graphic_pubinfos; + args.pubinfos.push(pubinfo.primary.value); + END; + args.pubinfo = (args.pubinfos.size) ? args.pubinfos.0 : ''; + + args.summaries = []; + FOR sub IN xml.findnodes('//*[@tag="520"]/*[@code="a"]'); + args.summaries.push(sub.textContent); + END; + args.summary = (args.summaries.size) ? args.summaries.0 : ''; + + # 250 gets pride of place for edition statement, and is the + # only logical choice for 880 graphic fields + graphic_880s = []; + get_graphic_880s(target_field='250'); + args.graphic_editions = graphic_880s; + args.editions = []; + FOR edition IN args.graphic_editions; + args.editions.push(edition.primary.value); + END; + + ed_hunt = xml.findnodes('//*[@tag="250"]/*[@code="a"]') || + xml.findnodes('//*[@tag="534"]/*[@code="b"]') || + xml.findnodes('//*[@tag="775"]/*[@code="b"]'); + FOR sub IN ed_hunt; + args.editions.push(sub.textContent); + END; + args.edition = (args.editions.size) ? args.editions.0 : ''; + + phys_content = []; + FOR sub IN 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(""); - - args.contents = xml.findnodes('//*[@tag="505"]').textContent; - - # capture all of the 520a's - args.summary = []; - FOR s IN xml.findnodes('//*[@tag="520"]/*[@code="a"]'); - args.summary.push(s.textContent); - END; - - # Marc CN - marcresults = xml.findnodes('//*[@tag="092"]/*[@code="a"]') || xml.findnodes('//*[@tag="099"]/*[@code="a"]'); - marcresults_content = []; - FOR sub IN marcresults; - marcresults_content.push(sub.textContent); - END; - IF marcresults_content.size; - attrs.marc_cn = marcresults_content.join(" "); - ELSE; - attrs.marc_cn = "N/A"; - END; - + phys_content.push(sub.textContent); + END; + args.phys_desc = phys_content.join(" "); + + graphic_880s = []; + get_graphic_880s(target_field='505'); + args.graphic_contents = graphic_880s; + FOR content IN args.graphic_contents; + args.contents.push(content.primary.value); + END; + args.content = (args.contents.size) ? args.contents.0 : ''; + + # Maintain contents_list in case any custom use was made of it + args.contents_list = []; + FOR sub IN xml.findnodes('//*[@tag="505"]'); + args.contents_list.push(sub.textContent); + END; + + # MARC Callnumber + args.marc_cns = []; + FOR sub IN xml.findnodes('//*[@tag="092" or @tag="099"]/*'); + args.marc_cns.push(sub.textContent); + END; + args.marc_cn = (args.marc_cns.size ) ? args.marc_cns.0 : ''; + + # clean up the ISBN args.isbn_clean = args.isbns.0.replace('\ .*', ''); # Extract the 856 URLs that are not otherwise represented by asset.uri's args.online_res = []; - FOR node IN xml.findnodes('//*[@tag="856"]'); + FOR node IN xml.findnodes('//*[@tag="856" and @ind1="4" and (@ind2="0" or @ind2="1")]'); IF node.findnodes('./*[@code="9" or @code="w" or @code="n"]'); NEXT; END; # asset.uri's - label = node.findnodes('./*[@code="z"]'); # XXX KCLS => y -> z - #notes = node.findnodes('./*[@code="z" or @code="3"]'); # XXX KCLS + label = node.findnodes('./*[@code="y"]'); + notes = node.findnodes('./*[@code="z" or @code="3"]'); FOR href IN node.findnodes('./*[@code="u"]'); NEXT UNLESS href; # it's possible for multiple $u's to exist within 1 856 tag. @@ -106,26 +244,158 @@ args.online_res.push({ href => href.textContent, link => (loop.first AND label) ? label.textContent : href.textContent, - #note => (loop.first) ? notes.textContent : '' # XXX KCLS - note => '' + note => (loop.first) ? notes.textContent : '' }); END; END; - + args.holdings = []; - FOR holding IN xml.findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]'); - args.holdings.push( - holding.getAttribute('label') + args.uris = []; + args.issns = []; + args.resolver_isbns = []; + args.resolver_issns = []; + + # we use $9 of ISBN and ISSN as a flag for e-version + FOR resolver_isbn IN xml.findnodes('//*[@tag="020"]/*[@code="9"]'); + IF resolver_isbn.textContent == "SFX" || resolver_isbn.textContent == "CUFTS"; + my_parent = resolver_isbn.parentNode(); + FOR resolver_isbn_val IN my_parent.findnodes('./*[@code="a"]'); + args.resolver_isbns.push( + resolver_isbn_val.textContent.replace('-', '').replace('\ .*', '') + ); + END; + END; + END; + + FOR resolver_issn IN xml.findnodes('//*[@tag="022"]/*[@code="9"]'); + IF resolver_issn.textContent == "SFX" || resolver_issn.textContent == "CUFTS"; + my_parent = resolver_issn.parentNode(); + FOR resolver_issn_val IN my_parent.findnodes('./*[@code="a"]'); + args.resolver_issns.push( + resolver_issn_val.textContent.replace('[^\d\-X]', '') + ); + END; + END; + END; + + # now snag all issns + FOR rawissn IN xml.findnodes('//*[@tag="022"]/*[@code="a"]'); + args.issns.push( + rawissn.textContent.replace('[^\d\-X]', '') ); END; + ou_hiding_disabled = ctx.org_hiding_disabled(); + + FOR volume IN xml.findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]'); + + # Check volume visibility - could push this into XPath + vol.label = volume.getAttribute('label'); + + # Prepend prefix, if any + prefix = volume.findnodes('./*[local-name()="call_number_prefix"][@ident!="-1"]'); + IF prefix.getAttribute('label') != ''; + vol.label = prefix.getAttribute('label') _ " " _ vol.label; + END; + + # Append prefix, if any + suffix = volume.findnodes('./*[local-name()="call_number_suffix"][@ident!="-1"]'); + IF suffix.getAttribute('label') != ''; + vol.label = vol.label _ " " _ suffix.getAttribute('label'); + END; + + vol.id = volume.getAttribute('id'); + NEXT IF volume.getAttribute('opac_visible') == 'false'; + NEXT IF volume.getAttribute('deleted') == 'true'; + + IF vol.label == '##URI##'; + FOR uri IN volume.findnodes('./*[local-name()="uris"]/*[local-name()="uri"]'); + res = {}; + res.href = uri.getAttribute('href'); + res.link = uri.getAttribute('label'); + res.note = uri.getAttribute('use_restriction'); + args.uris.push(res); + END; + NEXT; + ELSE; + copies = volume.findnodes('./*[local-name()="copies"]/*[local-name()="copy"]'); + FOR copy IN copies; + parts = copy.findnodes('./*[local-name()="monograph_parts"]/*[local-name()="monograph_part"]'); + FOREACH part IN parts; + part_label = part.getAttribute('label'); + LAST IF part_label != ''; + END; + # Check copy visibility + cp.deleted = copy.getAttribute('deleted'); + cp.visible = copy.getAttribute('opac_visible'); + NEXT IF (cp.deleted == 'true' OR cp.visible == 'false'); + + # Iterate through all of the children to determine visibility + FOR node IN cp.childNodes; + NEXT IF cp.visible == 'false'; + vis = node.getAttribute('opac_visible'); + del = node.getAttribute('deleted'); + IF vis == 'false' or del == 'true'; + cp.visible = 'false'; + END; + END; + + NEXT IF cp.visible == 'false'; + + loc = copy.findnodes('./*[local-name()="location"]'); + NEXT IF loc.getAttribute('opac_visible') == 'false'; + + circlib = copy.findnodes('./*[local-name()="circlib"]'); + NEXT IF circlib.getAttribute('opac_visible') == 'false'; + + status = copy.findnodes('./*[local-name()="status"]'); + NEXT IF status.getAttribute('opac_visible') == 'false'; + + UNLESS ou_hiding_disabled; + # extract the circ_lib id from the circ_lib node + circ_lib = copy.findnodes('./*[local-name()="circ_lib"]'); + circ_lib_id = circ_lib.getAttribute('id').replace('.*/', ''); + NEXT UNLESS ctx.org_within_hiding_scope(circ_lib_id); + END; + + holding = { + label => vol.label, + part_label => part_label, + location => loc.textContent, + library => circlib.textContent, + status => status.textContent, + barcode => copy.getAttribute('barcode'), + owner => volume.getAttribute('lib') + }; + args.holdings.push(holding); + part_label = ''; + END; + END; + END; + # Extract the copy count summary count_type = (ctx.is_staff) ? 'staff' : 'public'; + + # Consortial copy count summary first xpath = '//*[local-name()="counts"]/*[local-name()="count"][@type="' _ count_type _ '"]'; + args.copy_counts = {}; FOR node IN xml.findnodes(xpath); - args.copy_counts = {}; - FOR attr IN ['count', 'available', 'unshadow', 'transcendant']; - args.copy_counts.$attr = node.getAttribute(attr); + FOR attr IN ['count', 'available', 'unshadow', 'transcendant', 'org_unit']; + depth = node.getAttribute('depth'); + count_org_unit = node.getAttribute('org_unit'); + args.copy_counts.$depth.$attr = node.getAttribute(attr); + args.org_copy_counts.$count_org_unit.$attr = node.getAttribute(attr); + END; + END; + + # Get preferred library copy count + args.plib_copy_counts = {}; + count_type = 'pref_lib'; + xpath = '//*[local-name()="counts"]/*[local-name()="count"][@type="' _ count_type _ '"]'; + FOR node IN xml.findnodes(xpath); + FOR attr IN ['count', 'available', 'unshadow', 'transcendant', 'org_unit']; + depth = node.getAttribute('depth'); + args.plib_copy_counts.$depth.$attr = node.getAttribute(attr); END; END; @@ -134,11 +404,23 @@ node = xml.findnodes( '//*[local-name()="attributes"]/*[local-name()="field"][@name="' _ icon_style _ '"]'); IF node AND node.textContent; + type = node.textContent; args.format_label = node.getAttribute('coded-value') - args.format_icon = ctx.media_prefix _ '/images/format_icons/' _ icon_style _ '/' _ node.textContent _ '.png'; + args.schema.itemtype = schema_typemap.$type; + args.format_icon = ctx.media_prefix _ '/images/format_icons/' _ icon_style _ '/' _ type _ '.png'; LAST; END; END; + END; -%] + # Get the library or location group + # get_library() + # magically upgrades any use of 'loc' to 'locg', + # which is a superset of 'loc'. + BLOCK get_library; + loc_name = 'locg'; + loc_value = CGI.param(loc_name) || CGI.param('loc') || ctx.search_ou; + END; + +%] diff --git a/Open-ILS/web/js/ui/kcls/conify/global/config/search_templates.js b/Open-ILS/web/js/ui/kcls/conify/global/config/search_templates.js new file mode 100644 index 0000000000..c6f6ca91b7 --- /dev/null +++ b/Open-ILS/web/js/ui/kcls/conify/global/config/search_templates.js @@ -0,0 +1,427 @@ + + + var g = {}; + var templateList; + var template; + var DEFAULT = "--Default--"; + var myPackageDir = 'open_ils_staff_client'; + +function getSearchStash() { + try + { + if (typeof JSAN == 'undefined') + { + throw( document.getElementById("commonStrings").getString('common.jsan.missing') ); + } + JSAN.errorLevel = "die"; // none, warn, or die + JSAN.addRepository('/xul/server/'); + JSAN.use('util.error'); + g.error = new util.error(); + g.error.sdump('D_TRACE','getSearchStash() from search_settings.tt2 or search.tt2'); + + JSAN.use('OpenILS.data'); + g.data = new OpenILS.data(); + g.data.stash_retrieve(); + + //populate templateList, or not. + if (g.data.search_templates) + { + templateList = g.data.search_templates; + + //check for current template + if (g.data.current_search_template) + { + template = g.data.current_search_template; + } + } + else + { + templateList = new Array(); + } + } catch(E) { + try { g.error.standard_unexpected_error_alert('search_settings.tt2',E); } catch(F) { alert(E); } + return 0; + } +} + +//Creates, or edits, a search template based off the currently selected values +function create_template(tName) { + var template; + if (!tName || tName == DEFAULT) + { + alert("That is not a valid name."); + return; + } + template = getTemplateByName(tName, templateList); + + if (template == null) + { + var isNew = 1; + template = new Object(); + populateTemplate(template); + this.template = template; + templateList.push(template); + templateList.sort(compareTemplateNames) + } + else + { + if (confirm("Do you want to overwrite " + template.name + " template?")) + { + populateTemplate(template); + this.template = template; + } + else + { return;} + } + saveCurrentTemplate( template ); + saveTemplateList(templateList); + + //Add to templateSel and select if new template + if(isNew) + { + populateTemplateOptions(templateList); + selectOptionValue(templateSel, template.name); + } +} + +//Returns the selected values of of a given element +function getSelectedValues(elmnt) { +elmntVals = []; + var x = 0; + for (x=0;x templateB.name) + { return 1; } + else + { return 0; } +} + +//removes a template from the templateList object +function deleteTemplatefromTemplateList(tName, templateList) { + var index = getTemplateIndex(tName, templateList); + templateList.splice(index,1); + saveTemplateList(templateList); + return templateList; +} + +//Removes template from templateList and saved file if it exists and user wants it deleted +function removeTemplate(templateList, currentTemplate) { + var tempTemplate = getTemplateByName(textIn.value, templateList); + if (tempTemplate) + { + if(confirm("Are you sure you want to delete Template '" + tempTemplate.name + "'?")) + { + deleteTemplatefromTemplateList(tempTemplate.name, templateList); + populateTemplateOptions(templateList); + + //deleted template is the current template in use + if (currentTemplate.name == tempTemplate.name) + { + saveCurrentTemplate(null); + clearOptions(); + templateSel.selectedIndex = 0; + } + else + { + selectOptionValue(templateSel, currentTemplate.name); + } + textIn.value = ""; + } + else { + return; + } + } + else { + alert("Template '" + textIn.value + "' does not exist."); + } +} +//caches templateList and saves to file for posterity +function saveTemplateList(templateList) { + g.data.search_templates = templateList; + g.data.stash('search_templates'); + saveTemplateListToFile(templateList); +} + +//caches template currently in use and saves it to file +function saveCurrentTemplate(template) { + g.data.current_search_template = template; + g.data.stash('current_search_template'); + saveCurrentTemplateToFile(template) +} + +//clears all global row input fields +function clearGlobalRowInputs() { + var tBody = document.getElementById("adv_global_tbody"); + if(tBody) + { + var rows = tBody.getElementsByTagName("tr"); + if(rows.length > 0) + for (var i=0; i 0) { + inputs[0].value = ''; + } + } + } +} +//clears input fields associated with the pubdate +function clearPubDateInputs() + { + document.getElementById("adv_global_pub_date_1_input").value = ''; + document.getElementById("adv_global_pub_date_2_input").value = ''; + } diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd index 306f94114f..78c8b78958 100644 --- a/Open-ILS/web/opac/locale/en-US/lang.dtd +++ b/Open-ILS/web/opac/locale/en-US/lang.dtd @@ -2269,6 +2269,7 @@ + diff --git a/Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js b/Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js index 029531818a..e235de11d5 100644 --- a/Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js +++ b/Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js @@ -515,8 +515,38 @@ OpenILS.data.prototype = { } file.close(); - obj.print_list_defaults(); - obj.data_progress('Default print templates set. '); + JSAN.use('util.file'); var file = new util.file('yesterdays_search_template'); + if (file._file.exists()) { + try { + var x = file.get_content(); + if (x && x != "null") { + obj.current_search_template = JSON.parse(x); + obj.stash('current_search_template'); + obj.data_progress('Saved current search template retrieved from file. '); + } + } catch(E) { + alert(E); + } + } + file.close(); + + JSAN.use('util.file'); var file = new util.file('search_templates'); + if (file._file.exists()) { + try { + var x = file.get_content(); + if (x) { + obj.search_templates = JSON.parse(x); + obj.stash('search_templates'); + obj.data_progress('Saved search templates retrieved from file. '); + } + } catch(E) { + alert(E); + } + } + file.close(); + + + obj.print_list_defaults(); obj.data_progress('Default print templates set. '); obj.load_saved_print_templates(); obj.fetch_print_strategy(); JSAN.use('util.print'); (new util.print()).GetPrintSettings(); diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu.js b/Open-ILS/xul/staff_client/chrome/content/main/menu.js index 54248c885f..0f983da49d 100644 --- a/Open-ILS/xul/staff_client/chrome/content/main/menu.js +++ b/Open-ILS/xul/staff_client/chrome/content/main/menu.js @@ -774,6 +774,12 @@ main.menu.prototype = { ['oncommand'], function(event) { open_admin_page('font_settings.xul', 'menu.cmd_local_admin_fonts_and_sounds.tab', false, event); } ], + 'cmd_local_admin_search_templates' : [ + ['oncommand'], + function(event) { + open_eg_web_page('conify/global/config/search_templates', 'menu.cmd_local_admin_search_templates.tab', event); + } + ], 'cmd_local_admin_printer' : [ ['oncommand'], function(event) { open_admin_page('printer_settings.xul', 'menu.cmd_local_admin_printer.tab', false, event); } diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul index 9fe3ded47c..2e4d8d5e82 100644 --- a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul +++ b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul @@ -124,6 +124,7 @@ + + diff --git a/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties b/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties index b16e2a1830..d75651ed36 100644 --- a/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties +++ b/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties @@ -229,6 +229,7 @@ list.dump_extended_format.record_separator==-=-= list.line_number=# menu.cmd_survey_wizard.inadequate_perm=You are lacking the CREATE_SURVEY permission and/or working locations. menu.cmd_local_admin_fonts_and_sounds.tab=Global Font and Sound Settings +menu.cmd_local_admin_search_templates.tab=Search Templates menu.cmd_local_admin_printer.tab=Printer Settings Editor menu.cmd_local_admin_do_not_auto_attempt_print_setting.tab='Do Not Attempt Auto-Print' Setting menu.cmd_local_admin_closed_dates.tab=Closed Dates Editor -- 2.11.0