From 21abaf6f40c81c886f853ed30de8c60b1c52bfc4 Mon Sep 17 00:00:00 2001 From: blake Date: Tue, 14 Feb 2017 14:41:34 -0600 Subject: [PATCH] LP1573734_Link_to_sibling_metarecord_bibs_in_record_detail_page This feature will display sibling records when viewing a bib record in the OPAC. Altered Record.pm to gather up additional metarecord information to pass to misc_util.tt2 for parsing. Displayed on summary.tt2 styled in responsive in style.css.tt2. Also fixed the URL in mmr search results for single bib results in table.tt2. Transcendent bibs needed to be included in the unapi.mmr_mma function. This code requires the code from LP1629108. http://git.evergreen-ils.org/?p=working/Evergreen.git;a=shortlog; h=refs/heads/user/blake/LP1629108-metarecord-constituent-result-reroute Signed-off-by: blake Signed-off-by: Kathy Lussier --- .../perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm | 20 ++++ Open-ILS/src/sql/Pg/990.schema.unapi.sql | 3 +- ...bling_metarecord_bibs_in_record_detail_page.sql | 105 +++++++++++++++++++++ Open-ILS/src/templates/opac/css/style.css.tt2 | 36 +++++++ Open-ILS/src/templates/opac/parts/misc_util.tt2 | 44 ++++++++- .../src/templates/opac/parts/record/summary.tt2 | 70 ++++++++++++-- Open-ILS/src/templates/opac/parts/result/table.tt2 | 2 +- 7 files changed, 270 insertions(+), 10 deletions(-) create mode 100755 Open-ILS/src/sql/Pg/upgrade/XXXX.LP1573734_Link_to_sibling_metarecord_bibs_in_record_detail_page.sql diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm index 04f3cbea85..98aef3c272 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm @@ -215,6 +215,26 @@ sub load_record { $self->timelog("past added content stage 2"); + # Gather up metarecord info for display + # Let's start by getting the metarecord ID + my $mmr_id = OpenILS::Utils::CStoreEditor->new->json_query({ + select => { mmrsm => [ 'metarecord' ] }, + from => 'mmrsm', + where => { 'source' => $rec_id } + })->[0]->{metarecord}; + # If this record is apart of a meta group, I want to know more + if ( $mmr_id ) { + my (undef, @metarecord_data) = $self->get_records_and_facets([$mmr_id], undef, { + flesh => '{holdings_xml,mra}', + metarecord => 1, + site => $org_name, + depth => $depth, + pref_lib => $pref_ou + }); + my ($rec) = grep { $_->{mmr_id} == $mmr_id } @metarecord_data; + $ctx->{mmr_id} = $mmr_id; + $ctx->{mmr_data} = $rec; + } return Apache2::Const::OK; } diff --git a/Open-ILS/src/sql/Pg/990.schema.unapi.sql b/Open-ILS/src/sql/Pg/990.schema.unapi.sql index 154c284250..b1a407af84 100644 --- a/Open-ILS/src/sql/Pg/990.schema.unapi.sql +++ b/Open-ILS/src/sql/Pg/990.schema.unapi.sql @@ -1366,7 +1366,7 @@ CREATE OR REPLACE FUNCTION unapi.mmr_mra ( WITH aou AS (SELECT COALESCE(id, (evergreen.org_top()).id) AS id FROM actor.org_unit WHERE shortname = $5 LIMIT 1) SELECT source - FROM metabib.metarecord_source_map, aou + FROM metabib.metarecord_source_map mmsm, aou WHERE metarecord = $1 AND ( EXISTS ( SELECT 1 FROM asset.opac_visible_copies @@ -1375,6 +1375,7 @@ CREATE OR REPLACE FUNCTION unapi.mmr_mra ( LIMIT 1 ) OR EXISTS (SELECT 1 FROM located_uris(source, aou.id, $10) LIMIT 1) + OR EXISTS (SELECT 1 FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = mmsm.source LIMIT 1) ) ) SELECT cmra.aid, diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.LP1573734_Link_to_sibling_metarecord_bibs_in_record_detail_page.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.LP1573734_Link_to_sibling_metarecord_bibs_in_record_detail_page.sql new file mode 100755 index 0000000000..81b4cd629d --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.LP1573734_Link_to_sibling_metarecord_bibs_in_record_detail_page.sql @@ -0,0 +1,105 @@ + +BEGIN; + +SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version); + +CREATE OR REPLACE FUNCTION unapi.mmr_mra ( + obj_id BIGINT, + format TEXT, + ename TEXT, + includes TEXT[], + org TEXT, + depth INT DEFAULT NULL, + slimit HSTORE DEFAULT NULL, + soffset HSTORE DEFAULT NULL, + include_xmlns BOOL DEFAULT TRUE, + pref_lib INT DEFAULT NULL +) RETURNS XML AS $F$ + SELECT XMLELEMENT( + name attributes, + XMLATTRIBUTES( + CASE WHEN $9 THEN 'http://open-ils.org/spec/indexing/v1' ELSE NULL END AS xmlns, + 'tag:open-ils.org:U2@mmr/' || $1 AS metarecord + ), + (SELECT XMLAGG(foo.y) + FROM ( + WITH sourcelist AS ( + WITH aou AS (SELECT COALESCE(id, (evergreen.org_top()).id) AS id + FROM actor.org_unit WHERE shortname = $5 LIMIT 1) + SELECT source + FROM metabib.metarecord_source_map mmsm, aou + WHERE metarecord = $1 AND ( + EXISTS ( + SELECT 1 FROM asset.opac_visible_copies + WHERE record = source AND circ_lib IN ( + SELECT id FROM actor.org_unit_descendants(aou.id, $6)) + LIMIT 1 + ) + OR EXISTS (SELECT 1 FROM located_uris(source, aou.id, $10) LIMIT 1) + OR EXISTS (SELECT 1 FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = mmsm.source LIMIT 1) + ) + ) + SELECT cmra.aid, + XMLELEMENT( + name field, + XMLATTRIBUTES( + cmra.attr AS name, + cmra.value AS "coded-value", + cmra.aid AS "cvmid", + rad.composite, + rad.multi, + rad.filter, + rad.sorter, + cmra.source_list + ), + cmra.value + ) + FROM ( + SELECT DISTINCT aid, attr, value, STRING_AGG(x.id::TEXT, ',') AS source_list + FROM ( + SELECT v.source AS id, + c.id AS aid, + c.ctype AS attr, + c.code AS value + FROM metabib.record_attr_vector_list v + JOIN config.coded_value_map c ON ( c.id = ANY( v.vlist ) ) + ) AS x + JOIN sourcelist ON (x.id = sourcelist.source) + GROUP BY 1, 2, 3 + ) AS cmra + JOIN config.record_attr_definition rad ON (cmra.attr = rad.name) + UNION ALL + SELECT umra.aid, + XMLELEMENT( + name field, + XMLATTRIBUTES( + umra.attr AS name, + rad.composite, + rad.multi, + rad.filter, + rad.sorter + ), + umra.value + ) + FROM ( + SELECT DISTINCT aid, attr, value + FROM ( + SELECT v.source AS id, + m.id AS aid, + m.attr AS attr, + m.value AS value + FROM metabib.record_attr_vector_list v + JOIN metabib.uncontrolled_record_attr_value m ON ( m.id = ANY( v.vlist ) ) + ) AS x + JOIN sourcelist ON (x.id = sourcelist.source) + ) AS umra + JOIN config.record_attr_definition rad ON (umra.attr = rad.name) + ORDER BY 1 + + )foo(id,y) + ) + ) +$F$ LANGUAGE SQL STABLE; + +COMMIT; + diff --git a/Open-ILS/src/templates/opac/css/style.css.tt2 b/Open-ILS/src/templates/opac/css/style.css.tt2 index 413c3c92cb..e9fccea993 100644 --- a/Open-ILS/src/templates/opac/css/style.css.tt2 +++ b/Open-ILS/src/templates/opac/css/style.css.tt2 @@ -485,6 +485,33 @@ div.format_icon { margin-right: 17px; } +#metarecord_population { + overflow: hidden; + width: 40%; + padding-bottom: 10px; +} + +.metarecord_population_span_link { + line-height: 20px; +} + +.metarecord_population_format { + border-right: thin; + display: inline-block; + margin-right: 1em; + padding-right: 1em; + vertical-align: top; +} + +.metarecord_population_item_lang { + display: inline-block; + vertical-align: top; +} + +.metarecord_population_all { + padding-top:10px; +} + .result_util { border-bottom: 1px dotted [% css_colors.accent_light %]; padding-top: 6px; @@ -2002,6 +2029,15 @@ a.preflib_change { h2.rdetail_uris { clear: both; } + #metarecord_population { + overflow: hidden; + width: 100%; + } + .metarecord_population_span_link { + } + .metarecord_population_item_lang { + float: none; + } .search_catalog_lbl { margin-left: 0; white-space: nowrap; diff --git a/Open-ILS/src/templates/opac/parts/misc_util.tt2 b/Open-ILS/src/templates/opac/parts/misc_util.tt2 index a01ac503b9..d7ab819887 100644 --- a/Open-ILS/src/templates/opac/parts/misc_util.tt2 +++ b/Open-ILS/src/templates/opac/parts/misc_util.tt2 @@ -591,6 +591,7 @@ END; END; + mmr_unique_bib = []; # "mattype" == "custom marc format specifier" icon_style = ctx.get_cgf('opac.icon_attr').value || 'item_type'; formats_xpath = '//*[local-name()="attributes"]/*[local-name()="field"][@name="' _ icon_style _ '"]'; @@ -623,7 +624,9 @@ format.itemtype = schema_typemap.$type || 'CreativeWork'; format.search_format = ccvm.code; format.source_bibs = this_icon_source.split(','); - + FOR bib_source IN format.source_bibs; + IF NOT mmr_unique_bib.grep(bib_source).size; mmr_unique_bib.push(bib_source); END; + END; args.all_formats.push(format); # metarecords want all formats IF !args.format_label; @@ -635,7 +638,44 @@ END; END; END; - + + formats_xpath = '//*[local-name()="attributes"]/*[local-name()="field"][@name="item_lang"]'; + args.all_lang = []; + FOR node IN xml.findnodes(formats_xpath); + IF node AND node.textContent; + ccvm = ctx.get_ccvm(node.getAttribute('cvmid')); + NEXT IF ccvm.opac_visible == 'f'; + + lang = {}; + this_source = node.getAttribute('source_list'); + including = 'F'; + # Just display everything if we don't have the data + IF NOT args.mr_constituent_ids OR NOT this_source; + including = 'T'; + # We have an array of search-included bib IDs and we have the bib ID that this lang belongs to + ELSE; + FOR mr_constituent_id IN args.mr_constituent_ids; + IF this_source.split(',').grep('^' _ mr_constituent_id _ '$' ).size; + # This bib appears to be in the array of filtered bibs + including = 'T'; + END; + END; + END; + IF including == 'T'; + lang.label = ccvm.search_label || ccvm.value; + lang.itemtype = schema_typemap.$type || 'CreativeWork'; + lang.search_format = node.textContent; + lang.source_bibs = this_source.split(','); + FOR bib_source IN lang.source_bibs; + IF NOT mmr_unique_bib.grep(bib_source).size; mmr_unique_bib.push(bib_source); END; + END; + + args.all_lang.push(lang); # metarecords want all + END; + END; + END; + args.mmr_unique_bib = mmr_unique_bib; + args.bibid = []; FOR bibid IN xml.findnodes('//*[@tag="901"]/*[@code="c"]'); args.bibid.push(bibid.textContent); diff --git a/Open-ILS/src/templates/opac/parts/record/summary.tt2 b/Open-ILS/src/templates/opac/parts/record/summary.tt2 index 1068e72b30..d80958dc1b 100644 --- a/Open-ILS/src/templates/opac/parts/record/summary.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/summary.tt2 @@ -166,11 +166,12 @@ IF num_uris > 0; [%- IF num_uris > 1 %][% END %] [%- END %] -[%- # Hold/copy summary - IF ctx.copy_summary.0.count -%]
-[%- INCLUDE "opac/parts/record/copy_counts.tt2" %] +[%- +# Hold/copy summary +IF ctx.copy_summary.0.count; +INCLUDE "opac/parts/record/copy_counts.tt2"; +%]

[% l('Current holds') %]

@@ -190,9 +191,66 @@ IF num_uris > 0; %]

-[%- INCLUDE "opac/parts/record/copy_table.tt2" copies=ctx.copies %] -
[%- END %] +
+[%- +# l( 'mmr id = ' _ ctx.mmr_id ); +# l( 'mmr data = ' _ ctx.mmr_data ); +mmr_attrs = {marc_xml => ctx.mmr_data.marc_xml}; +PROCESS get_marc_attrs args=mmr_attrs; + +IF args.mmr_unique_bib.size > 1; +%] +

View Other Formats and Editions

+ +[%- IF mmr_attrs.format_label; + FOR format IN mmr_attrs.all_formats; + + link = mkurl(ctx.opac_root _ '/record/' _ format.source_bibs.0); + IF format.source_bibs.size > 1; + link = mkurl( ctx.opac_root _ '/results', { modifier => 'metabib', metarecord => ctx.mmr_id, 'fi:icon_format' => format.search_format, 'fi:from_metarecord' => ctx.mmr_id }, stop_parms.merge(expert_search_parms, general_search_parms, browse_search_parms, facet_search_parms, ['qtype','fi:search_format','fi:icon_format','fi:item_lang','fi:from_metarecord']) ); + END; -%] + + + [% format.label | html %] + ([%- l( format.source_bibs.size ) %]) +
+ + [%- END %] +
+ [%- IF mmr_attrs.all_lang.size > 0 %] + + [% FOR lang IN mmr_attrs.all_lang; + link = mkurl(ctx.opac_root _ '/record/' _ lang.source_bibs.0); + IF lang.source_bibs.size > 1; + USE url(ctx.opac_root _ '/results'); + link = mkurl( ctx.opac_root _ '/results', { modifier => 'metabib', metarecord => ctx.mmr_id, 'fi:item_lang' => lang.search_format, 'fi:from_metarecord' => ctx.mmr_id }, stop_parms.merge(expert_search_parms, general_search_parms, browse_search_parms, facet_search_parms, ['qtype','fi:search_format','fi:icon_format','fi:item_lang','fi:from_metarecord']) ); + END; -%] + + + [% lang.label | html %] + ([%- l( lang.source_bibs.size ) %]) +
+ [%- END %] +
+[%- END %] +
+ [% + link = mkurl( ctx.opac_root _ '/results', { modifier => 'metabib', metarecord => ctx.mmr_id, 'fi:from_metarecord' => ctx.mmr_id }, stop_parms.merge(expert_search_parms, general_search_parms, browse_search_parms, facet_search_parms, ['qtype','fi:search_format','fi:icon_format','fi:item_lang','fi:from_metarecord'] ) ); + %] + + View all [%- args.mmr_unique_bib.size %] formats and editions +
+
+[%- END; +END # ending tag for IF args.mmr_unique_bib.size > 1; %] +
+[%- +IF ctx.copy_summary.0.count; +INCLUDE "opac/parts/record/copy_table.tt2" copies=ctx.copies; +END; + %] +

[% l("Record details") %]

    diff --git a/Open-ILS/src/templates/opac/parts/result/table.tt2 b/Open-ILS/src/templates/opac/parts/result/table.tt2 index 8f5902270d..5f3cbc39cf 100644 --- a/Open-ILS/src/templates/opac/parts/result/table.tt2 +++ b/Open-ILS/src/templates/opac/parts/result/table.tt2 @@ -86,7 +86,7 @@ ELSE; # for MR, bre_id refers to the master and in # this case, only, record - record_url = mkurl(ctx.opac_root _ '/record/' _ rec.bre_id, { badges => rec.badges.join(',') }); + record_url = mkurl(ctx.opac_root _ '/record/' _ attrs.mr_constituent_ids.0, { badges => rec.badges.join(',') }); END; hold_type = 'M'; ELSE; -- 2.11.0