From 1f55d0e4764e06d9b6170ef4977cd26a9431214c Mon Sep 17 00:00:00 2001 From: Dan Scott Date: Sun, 25 Aug 2013 00:40:46 -0400 Subject: [PATCH] Add structured data for holdings via http://schema.org/Offer Map library name to Offer/seller, shelving location to Offer/availableAtOrFrom, call number to Offer/sku, barcode to Offer/serialNumber, copy status to Offer/availability, and ISBN-13 to gtin13. Use the additionalType of Product to give these offers an obvious relationship. Surface copy counts as AggregateOffer instances. Cut over to RDFa Lite instead of microdata for schema.org, as RDFa Lite is more easily extensible with other vocabularies, and is as accepted as microdata by schema.org processors. Signed-off-by: Dan Scott Signed-off-by: Ben Shum --- .../perlmods/lib/OpenILS/Application/AppUtils.pm | 1 + .../src/templates/opac/parts/ac_google_books.tt2 | 2 +- Open-ILS/src/templates/opac/parts/misc_util.tt2 | 22 +++++++++++++++++++- .../src/templates/opac/parts/record/authors.tt2 | 16 +++++++-------- Open-ILS/src/templates/opac/parts/record/body.tt2 | 2 +- .../src/templates/opac/parts/record/contents.tt2 | 2 +- .../templates/opac/parts/record/copy_counts.tt2 | 9 ++++++-- .../src/templates/opac/parts/record/copy_table.tt2 | 24 ++++++++++++++-------- .../src/templates/opac/parts/record/subjects.tt2 | 2 +- .../src/templates/opac/parts/record/summary.tt2 | 20 +++++++++++------- 10 files changed, 70 insertions(+), 30 deletions(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm index 00d7bf2009..5a6d38582d 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm @@ -1961,6 +1961,7 @@ sub basic_opac_copy_query { {column => 'holdable', alias => 'location_holdable'} ], ccs => [ + {column => 'id', alias => 'status_code'}, {column => 'name', alias => 'copy_status'}, {column => 'holdable', alias => 'status_holdable'} ], diff --git a/Open-ILS/src/templates/opac/parts/ac_google_books.tt2 b/Open-ILS/src/templates/opac/parts/ac_google_books.tt2 index 3dbb5f988e..cbec24f1e3 100644 --- a/Open-ILS/src/templates/opac/parts/ac_google_books.tt2 +++ b/Open-ILS/src/templates/opac/parts/ac_google_books.tt2 @@ -100,7 +100,7 @@ function GBShowHidePreview(from_button) { dojo.addOnLoad(function() { var spans = dojo.query('li.rdetail_isbns span.rdetail_value'); for (var i = 0; i < spans.length; i++) { - var prop = spans[i].getAttribute('itemprop'); + var prop = spans[i].getAttribute('property'); if (!prop) { continue; } diff --git a/Open-ILS/src/templates/opac/parts/misc_util.tt2 b/Open-ILS/src/templates/opac/parts/misc_util.tt2 index 3f31205dd8..363318d852 100644 --- a/Open-ILS/src/templates/opac/parts/misc_util.tt2 +++ b/Open-ILS/src/templates/opac/parts/misc_util.tt2 @@ -91,6 +91,17 @@ schema_typemap.e = 'http://schema.org/Map'; schema_typemap.j = 'http://schema.org/MusicAlbum'; + # Hard-coded to match defaults in config.copy_status for all OPAC-visible statuses + schema_copy_status = {}; + schema_copy_status.0 = ''; # Available + schema_copy_status.1 = ''; # Checked out + schema_copy_status.5 = ''; # In process + schema_copy_status.6 = ''; # In transit + schema_copy_status.7 = ''; # Reshelving + schema_copy_status.8 = ''; # On holds shelf + schema_copy_status.9 = ''; # On order + schema_copy_status.12 = ''; # Reserves + args.isbns = []; FOR isbn IN xml.findnodes('//*[@tag="020"]/*[@code="a"]'); args.isbns.push(isbn.textContent); @@ -228,6 +239,14 @@ # clean up the ISBN args.isbn_clean = args.isbns.0.replace('\ .*', ''); + FOR isbn IN args.isbns; + clean_isbn = isbn.replace('\ .*', ''); + clean_isbn = clean_isbn.replace('-', ''); + IF clean_isbn.length == 13; + args.gtin13 = clean_isbn; + LAST; + END; + END; # Extract the 856 URLs that are not otherwise represented by asset.uri's args.online_res = []; @@ -366,6 +385,7 @@ location => loc.textContent, library => circlib.textContent, status => status.textContent, + status_code => status.getAttribute('ident'), barcode => copy.getAttribute('barcode'), owner => volume.getAttribute('lib') }; @@ -408,7 +428,7 @@ IF node AND node.textContent; type = node.textContent; args.format_label = node.getAttribute('coded-value') - args.schema.itemtype = schema_typemap.$type; + args.schema.itemtype = schema_typemap.$type || 'CreativeWork'; args.format_icon = ctx.media_prefix _ '/images/format_icons/' _ icon_style _ '/' _ type _ '.png'; LAST; END; diff --git a/Open-ILS/src/templates/opac/parts/record/authors.tt2 b/Open-ILS/src/templates/opac/parts/record/authors.tt2 index 005b48a0f1..6d25b3c51c 100644 --- a/Open-ILS/src/templates/opac/parts/record/authors.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/authors.tt2 @@ -68,28 +68,28 @@ BLOCK build_author_links; # schema.org changes IF type == 'author'; IF tag.substr(1,2) == '10' && args.schema.itemtype && args.schema.itemtype.match('MusicAlbum'); - iprop = ' itemtype="http://schema.org/MusicGroup" itemscope itemprop="byArtist"'; + iprop = ' typeof="MusicGroup" property="byArtist"'; ELSIF tag.substr(1,2) == '00'; - iprop = ' itemtype="http://schema.org/Person" itemscope itemprop="author"'; + iprop = ' typeof="Person" property="author"'; ELSE; - iprop = ' itemtype="http://schema.org/Organization" itemscope itemprop="author"'; + iprop = ' typeof="Organization" property="author"'; END; ELSIF type == 'added'; IF tag.substr(1,2) == '00'; - iprop = ' itemtype="http://schema.org/Person" itemscope itemprop="contributor"'; + iprop = ' typeOf="Person" property="contributor"'; ELSE; - iprop = ' itemtype="http://schema.org/Organization" itemscope itemprop="contributor"'; + iprop = ' typeOf="Organization" property="contributor"'; END; END; ''; - IF iprop; ''; END; + IF iprop; ''; END; term.replace('^\s+', ''); IF iprop; ''; END; IF birthdate; - ' ' _ birthdate _ '-'; + ' ' _ birthdate _ '-'; END; IF deathdate; - '' _ deathdate _ ''; + '' _ deathdate _ ''; END; ''; FOREACH link880 IN graphics; diff --git a/Open-ILS/src/templates/opac/parts/record/body.tt2 b/Open-ILS/src/templates/opac/parts/record/body.tt2 index 2e74d66b21..b8ba910206 100644 --- a/Open-ILS/src/templates/opac/parts/record/body.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/body.tt2 @@ -4,7 +4,7 @@ stop_parms = ['expand','cnoffset','copy_offset','copy_limit']; ctx.record_attrs = attrs; # capture for JS %] -
+
[%- INCLUDE "opac/parts/record/navigation.tt2" %] [%- IF ctx.bib_is_dead %]
diff --git a/Open-ILS/src/templates/opac/parts/record/contents.tt2 b/Open-ILS/src/templates/opac/parts/record/contents.tt2 index fcf9e54b3d..29fc33b4cd 100644 --- a/Open-ILS/src/templates/opac/parts/record/contents.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/contents.tt2 @@ -187,7 +187,7 @@ END -%] [% cont.label %] - [% content %] + [% content %] [%- END; %] [%- END; %] diff --git a/Open-ILS/src/templates/opac/parts/record/copy_counts.tt2 b/Open-ILS/src/templates/opac/parts/record/copy_counts.tt2 index a400aad9cd..fd97eabc6f 100644 --- a/Open-ILS/src/templates/opac/parts/record/copy_counts.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/copy_counts.tt2 @@ -17,7 +17,9 @@ ou_name = cp_org_unit.name; displayed_ous.$ou_name = 1; %] -
  • +
  • + + [% l('[quant,_1,copy,copies] at [_2].', ou_avail, ou_name) | html %] [%- this_depth = ctx.get_aou(ou_id).ou_type.depth; IF ou_avail > 0 && this_depth != ctx.copy_depth %] @@ -35,7 +37,10 @@ UNLESS depth < 0 || displayed_ous.exists(ou_name); %] [%- IF attrs.plib_copy_counts.$depth.count > 0; %] -
  • [% +
  • + + + [%- l('[_1] of [quant,_2,copy,copies] available at [_3].', attrs.plib_copy_counts.$depth.available, attrs.plib_copy_counts.$depth.count, diff --git a/Open-ILS/src/templates/opac/parts/record/copy_table.tt2 b/Open-ILS/src/templates/opac/parts/record/copy_table.tt2 index 5bab2b7890..57d1d41799 100644 --- a/Open-ILS/src/templates/opac/parts/record/copy_table.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/copy_table.tt2 @@ -89,11 +89,11 @@ END; # FOREACH bib callnum = callnum _ " " _ callnum_suffix; END; -%] - + [%- IF serial_holdings %] [%- copy_info.holding_label | html; -%] - [%- ELSE %] + [%- ELSE %] [%- org_name = ctx.get_aou(copy_info.circ_lib).name; lib_url = ctx.get_org_setting(copy_info.circ_lib, 'lib.info_url'); @@ -101,17 +101,22 @@ END; # FOREACH bib org_name | html; IF lib_url; ''; END; -%] + [% END %] - [% callnum | html %] [% IF ctx.get_org_setting(CGI.param('loc') OR ctx.aou_tree.id, 'sms.enable') == 1 %](Text)[% END %] + [% callnum | html %] [% IF ctx.get_org_setting(CGI.param('loc') OR ctx.aou_tree.id, 'sms.enable') == 1 %](Text)[% END %] [%- IF has_parts == 'true' %] [% copy_info.part_label | html %] [%- END %] - + [%- IF ctx.is_staff -%] [% copy_info.barcode | html %] [%- ELSE -%][% copy_info.barcode | html %] - [%- END -%] - [% copy_info.copy_location | html %] + [%- END -%] + [%- IF attrs.gtin13; + ''; + END; -%] + + [% copy_info.copy_location | html %] [%- IF ctx.is_staff %] [% copy_info.age_protect ? @@ -171,7 +176,10 @@ END; # FOREACH bib l("Not holdable"); END %] [%- END %] - [% copy_info.copy_status | html %] + [%- + schema_copy_status.${copy_info.status_code}; + copy_info.copy_status | html; + -%] [% IF copy_info.due_date; date.format( @@ -185,7 +193,7 @@ END; # FOREACH bib [% IF copy_info.notes; %] [% FOREACH note IN copy_info.notes; %] -  [% note.title | html %]: [% note.value | html %] +  [% note.title | html %]: [% note.value | html %] [% END %] [% END %] diff --git a/Open-ILS/src/templates/opac/parts/record/subjects.tt2 b/Open-ILS/src/templates/opac/parts/record/subjects.tt2 index 3914908990..5812690b46 100644 --- a/Open-ILS/src/templates/opac/parts/record/subjects.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/subjects.tt2 @@ -68,7 +68,7 @@ [% subj.label %] - [% content %] + [% content %] diff --git a/Open-ILS/src/templates/opac/parts/record/summary.tt2 b/Open-ILS/src/templates/opac/parts/record/summary.tt2 index a38bd54f7e..b9a91a89ad 100644 --- a/Open-ILS/src/templates/opac/parts/record/summary.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/summary.tt2 @@ -61,7 +61,7 @@ [% attrs.format_label %]
  • [%- END %] -

    [% attrs.title_extended | html %]

    +

    [% attrs.title_extended | html %]

    [%- FOR link880 IN attrs.graphic_titles; FOR alt IN link880.graphic; @@ -108,8 +108,14 @@ IF num_uris > 0;
    [%- IF num_uris > 1 %]
      [% END %] [%- FOR uri IN merged_uris %] - [%- IF num_uris == 1 %]

      [% ELSE %]

    • [% END %] + [%- IF num_uris == 1 -%] +

      + [%- ELSE -%] +

    • + [%- END -%] [% uri.link %][% ' - ' _ uri.note IF uri.note %] + + [%- IF attrs.gtin13; ''; END; %] [%- IF num_uris == 1 %]

      [% ELSE %]
    • [% END %] [%- END %] [%- IF num_uris > 1 %]
    [% END %] @@ -148,7 +154,7 @@ IF num_uris > 0; [%- IF attrs.isbns.0; FOR isbn IN attrs.isbns %]
  • [% l('ISBN:'); %] - [% isbn | html %] + [% isbn | html %]
  • [%- END %] [%- END %] @@ -189,14 +195,14 @@ IF num_uris > 0; [%- IF attrs.publisher %]
  • [% l("Publisher:") %] - + [%- IF attrs.pubplace; %] - [% attrs.pubplace | html; %] + [% attrs.pubplace | html; %] [%- END; %] - [% attrs.publisher | html; %] + [% attrs.publisher | html; %] [%- IF attrs.pubdate; %] - + [% attrs.pubdate | html; %] [%- END; %] [%- IF attrs.graphic_pubinfos.size > 0; -- 2.11.0