First inklings of schema.org support for library pages
authorDan Scott <dscott@laurentian.ca>
Sat, 26 Oct 2013 21:32:22 +0000 (17:32 -0400)
committerDan Wells <dbw2@calvin.edu>
Tue, 21 Jan 2014 19:57:42 +0000 (14:57 -0500)
Adds a TPAC page where the information for a given library can be publicly
exposed; in addition, that information is marked up with schema.org structured
data so that, for example, a search engine can offer up the hours of operation
and contact information for a given branch right on the search results page.

We give the content-wrapper a main-content for indentation, to be consistent
with other pages in the TPAC.

We also add the cargo-cult common-full-pad div for a bottom margin.

Signed-off-by: Dan Scott <dscott@laurentian.ca>
Signed-off-by: Dan Wells <dbw2@calvin.edu>
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Library.pm [new file with mode: 0644]
Open-ILS/src/templates/opac/library.tt2 [new file with mode: 0644]
Open-ILS/src/templates/opac/parts/library/hours.tt2 [new file with mode: 0644]

index 0af9399..e5ceb0f 100644 (file)
@@ -20,6 +20,7 @@ use Time::HiRes;
 use OpenILS::WWW::EGCatLoader::Util;
 use OpenILS::WWW::EGCatLoader::Account;
 use OpenILS::WWW::EGCatLoader::Browse;
 use OpenILS::WWW::EGCatLoader::Util;
 use OpenILS::WWW::EGCatLoader::Account;
 use OpenILS::WWW::EGCatLoader::Browse;
+use OpenILS::WWW::EGCatLoader::Library;
 use OpenILS::WWW::EGCatLoader::Search;
 use OpenILS::WWW::EGCatLoader::Record;
 use OpenILS::WWW::EGCatLoader::Container;
 use OpenILS::WWW::EGCatLoader::Search;
 use OpenILS::WWW::EGCatLoader::Record;
 use OpenILS::WWW::EGCatLoader::Container;
@@ -121,6 +122,7 @@ sub load {
     return $self->load_simple("advanced") if
         $path =~ m:opac/(advanced|numeric|expert):;
 
     return $self->load_simple("advanced") if
         $path =~ m:opac/(advanced|numeric|expert):;
 
+    return $self->load_library if $path =~ m|opac/library|;
     return $self->load_rresults if $path =~ m|opac/results|;
     return $self->load_print_record if $path =~ m|opac/record/print|;
     return $self->load_record if $path =~ m|opac/record/\d|;
     return $self->load_rresults if $path =~ m|opac/results|;
     return $self->load_print_record if $path =~ m|opac/record/print|;
     return $self->load_record if $path =~ m|opac/record/\d|;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Library.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Library.pm
new file mode 100644 (file)
index 0000000..18094dd
--- /dev/null
@@ -0,0 +1,62 @@
+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: 
+#   library : aou object
+#   parent: aou object
+sub load_library {
+    my $self = shift;
+    my %kwargs = @_;
+    my $ctx = $self->ctx;
+    $ctx->{page} = 'library';  
+
+    $self->timelog("load_library() began");
+
+    my $lib_id = $ctx->{page_args}->[0];
+    $lib_id = $self->_resolve_org_id_or_shortname($lib_id);
+
+    return Apache2::Const::HTTP_BAD_REQUEST 
+        unless $lib_id;
+
+    my $aou = $ctx->{get_aou}->($lib_id);
+    my $sname = $aou->parent_ou;
+
+    $ctx->{library} = $aou;
+    if ($aou->parent_ou) {
+        $ctx->{parent} = $ctx->{get_aou}->($aou->parent_ou);
+    }
+
+    $self->timelog("got basic lib info");
+
+    # Get mailing address
+    if ($aou->mailing_address) {
+        my $session = OpenSRF::AppSession->create("open-ils.actor");
+        $ctx->{mailing_address} =
+            $session->request('open-ils.actor.org_unit.address.retrieve',
+            $aou->mailing_address)->gather(1);
+    }
+
+    # Get current hours of operation
+    my $hours = $self->editor->retrieve_actor_org_unit_hours_of_operation($lib_id);
+    if ($hours) {
+        $ctx->{hours} = $hours;
+        # Generate naive schema.org format
+        $ctx->{hours_schema} = "Mo " . substr($hours->dow_0_open, 0, 5) . "-" . substr($hours->dow_0_close, 0, 5) .
+            ",Tu " . substr($hours->dow_1_open, 0, 5) . "-" . substr($hours->dow_1_close, 0, 5) .
+            ",We " . substr($hours->dow_2_open, 0, 5) . "-" . substr($hours->dow_2_close, 0, 5) .
+            ",Th " . substr($hours->dow_3_open, 0, 5) . "-" . substr($hours->dow_3_close, 0, 5) .
+            ",Fr " . substr($hours->dow_4_open, 0, 5) . "-" . substr($hours->dow_4_close, 0, 5) .
+            ",Sa " . substr($hours->dow_5_open, 0, 5) . "-" . substr($hours->dow_5_close, 0, 5) .
+            ",Su " . substr($hours->dow_6_open, 0, 5) . "-" . substr($hours->dow_6_close, 0, 5);
+    }
+
+    return Apache2::Const::OK;
+}
+
+1;
diff --git a/Open-ILS/src/templates/opac/library.tt2 b/Open-ILS/src/templates/opac/library.tt2
new file mode 100644 (file)
index 0000000..0a33e2d
--- /dev/null
@@ -0,0 +1,57 @@
+[%- PROCESS "opac/parts/header.tt2";
+    WRAPPER "opac/parts/base.tt2";
+    INCLUDE "opac/parts/topnav.tt2";
+    ctx.page_title = l("Library details: [_1]", ctx.library.name);
+-%]
+    [%- INCLUDE "opac/parts/searchbar.tt2" %]
+<div id="content-wrapper">
+    <div id="main-content" class="content-wrapper-library-page" vocab="http://schema.org/" typeof="Library">
+    <h1 property="name">[% ctx.library.name | html %]</h1>
+
+    [%-
+        lib_url = ctx.get_org_setting(ctx.library.id, 'lib.info_url');
+        IF lib_url;
+            '<div id="library-url"><a href="'; lib_url | url; '" property="url">'; l('External web site'); '</a></div>';
+        END;
+    -%]
+
+    [%- IF ctx.hours; %]
+        [%- INCLUDE "opac/parts/library/hours.tt2"; %]
+    [% END; -%]
+
+    [%- IF (ctx.library.email OR ctx.library.phone); %]
+    <h2 id="contact-info">[% l('Contact information') %]</h2>
+    [%- IF ctx.library.email; %]
+        <div>[% l('Email address: ') %]<a href="mailto:[% ctx.library.email | html %]" property="email">[% ctx.library.email | html %]</a></div>
+    [%- END; %]
+    [%- IF ctx.library.phone; %]
+        <div>[% l('Telephone: ') %]<a href="tel:[% ctx.library.phone | html %]" property="telephone">[% ctx.library.phone | html %]</a></div>
+    [% END; %]
+    [% END; %]
+
+    [%- IF ctx.library.mailing_address; %]
+    <div id="addresses">
+        <div id="mailing" property="location address" typeof="PostalAddress">
+            <h3 property="contactType">[% l('Mailing address') %]</h3>
+            <span property="streetAddress">[% ctx.mailing_address.street1 | html %]
+            [%- IF ctx.mailing_address.street2; "<br />"; ctx.mailing_address.street2 | html; END; %]
+            </span><br />
+            <span property="addressLocality">[% ctx.mailing_address.city | html %]</span><br />
+            <span property="addressRegion">[% ctx.mailing_address.state | html %]</span><br />
+            <span property="addressCountry">[% ctx.mailing_address.country | html %]</span><br />
+            <span property="postalCode">[% ctx.mailing_address.post_code | html %]</span><br />
+        </div>
+    </div>
+    [%- END; %]
+
+    [%- IF ctx.library.parent_ou; %]
+    <h2>Branch relationship</h2>
+    <div id="branch-info">[% l('Parent library: ') %]
+        <a property="branchOf" href="[% mkurl(ctx.opac_root _ '/library/' _ ctx.parent.shortname, {}, 1) %]">[% ctx.parent.name | html %]</a>
+    </div>
+    [%  END; -%]
+
+    <div class="common-full-pad"></div>
+    </div>
+[%- END %]
+</div>
diff --git a/Open-ILS/src/templates/opac/parts/library/hours.tt2 b/Open-ILS/src/templates/opac/parts/library/hours.tt2
new file mode 100644 (file)
index 0000000..37513b1
--- /dev/null
@@ -0,0 +1,57 @@
+<h2>[% l('Opening hours') %]</h2>
+[%- IF ctx.hours.dow_0_open == ctx.hours.dow_0_close; %]
+<div class="opening-hours">[% l('Monday: closed') %]</div>
+[%- ELSE %]
+<div class="opening-hours" property="openingHoursSpecification" typeof="OpeningHoursSpecification"><link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Monday" />[%
+    l('Monday: [_1]-[_2]', '<span property="opens">' _ ctx.hours.dow_0_open.substr(0, 5) _ '</span>',
+     '<span property="closes">' _ ctx.hours.dow_0_close.substr(0, 5) _ '</span>') -%]
+</div>
+[%- END %]
+[%- IF ctx.hours.dow_1_open == ctx.hours.dow_1_close; %]
+<div class="opening-hours">[% l('Tuesday: closed') %]</div>
+[%- ELSE %]
+<div class="opening-hours" property="openingHoursSpecification" typeof="OpeningHoursSpecification"><link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Tuesday" />[%
+    l('Tuesday: [_1]-[_2]', '<span property="opens">' _ ctx.hours.dow_1_open.substr(0, 5) _ '</span>',
+     '<span property="closes">' _ ctx.hours.dow_1_close.substr(0, 5) _ '</span>') -%]
+</div>
+[%- END %]
+[%- IF ctx.hours.dow_2_open == ctx.hours.dow_2_close; %]
+<div class="opening-hours">[% l('Wednesday: closed') %]</div>
+[%- ELSE %]
+<div class="opening-hours" property="openingHoursSpecification" typeof="OpeningHoursSpecification"><link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Wednesday" />[%
+    l('Wednesday: [_1]-[_2]', '<span property="opens">' _ ctx.hours.dow_2_open.substr(0, 5) _ '</span>',
+     '<span property="closes">' _ ctx.hours.dow_2_close.substr(0, 5) _ '</span>') -%]
+</div>
+[%- END %]
+[%- IF ctx.hours.dow_3_open == ctx.hours.dow_3_close; %]
+<div class="opening-hours">[% l('Thursday: closed') %]</div>
+[%- ELSE %]
+<div class="opening-hours" property="openingHoursSpecification" typeof="OpeningHoursSpecification"><link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Thursday" />[%
+    l('Thursday: [_1]-[_2]', '<span property="opens">' _ ctx.hours.dow_3_open.substr(0, 5) _ '</span>',
+     '<span property="closes">' _ ctx.hours.dow_3_close.substr(0, 5) _ '</span>') -%]
+</div>
+[%- END %]
+[%- IF ctx.hours.dow_4_open == ctx.hours.dow_4_close; %]
+<div class="opening-hours">[% l('Friday: closed') %]</div>
+[%- ELSE %]
+<div class="opening-hours" property="openingHoursSpecification" typeof="OpeningHoursSpecification"><link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Friday" />[%
+    l('Friday: [_1]-[_2]', '<span property="opens">' _ ctx.hours.dow_4_open.substr(0, 5) _ '</span>',
+     '<span property="closes">' _ ctx.hours.dow_4_close.substr(0, 5) _ '</span>') -%]
+</div>
+[%- END %]
+[%- IF ctx.hours.dow_5_open == ctx.hours.dow_5_close; %]
+<div class="opening-hours">[% l('Saturday: closed') %]</div>
+[%- ELSE %]
+<div class="opening-hours" property="openingHoursSpecification" typeof="OpeningHoursSpecification"><link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Saturday" />[%
+    l('Saturday: [_1]-[_2]', '<span property="opens">' _ ctx.hours.dow_5_open.substr(0, 5) _ '</span>',
+     '<span property="closes">' _ ctx.hours.dow_5_close.substr(0, 5) _ '</span>') -%]
+</div>
+[%- END %]
+[%- IF ctx.hours.dow_6_open == ctx.hours.dow_6_close; %]
+<div class="opening-hours">[% l('Sunday: closed') %]</div>
+[%- ELSE %]
+<div class="opening-hours" property="openingHoursSpecification" typeof="OpeningHoursSpecification"><link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Sunday" />[%
+    l('Sunday: [_1]-[_2]', '<span property="opens">' _ ctx.hours.dow_6_open.substr(0, 5) _ '</span>',
+     '<span property="closes">' _ ctx.hours.dow_6_close.substr(0, 5) _ '</span>') -%]
+</div>
+[%- END %]