[Koha-patches] [PATCH] bug_16034 Add overdrive info to the users page in the public interface
Srdjan
srdjan at catalyst.net.nz
Thu Mar 10 05:31:39 CET 2016
---
.../bootstrap/en/includes/overdrive-checkout.inc | 19 ++
.../bootstrap/en/modules/opac-overdrive-search.tt | 17 +-
.../opac-tmpl/bootstrap/en/modules/opac-user.tt | 23 ++
koha-tmpl/opac-tmpl/bootstrap/js/overdrive.js | 359 +++++++++++++++++++++
opac/opac-overdrive-search.pl | 1 +
opac/opac-user.pl | 6 +
opac/svc/overdrive | 139 ++++++++
7 files changed, 562 insertions(+), 2 deletions(-)
create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/includes/overdrive-checkout.inc
create mode 100755 opac/svc/overdrive
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/overdrive-checkout.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/overdrive-checkout.inc
new file mode 100644
index 0000000..a8d60bb
--- /dev/null
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/overdrive-checkout.inc
@@ -0,0 +1,19 @@
+<div id="overdrive-checkout" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="overdrive-checkout-label" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
+ <h3 id="overdrive-checkout-label">Checkout</h3>
+ </div>
+ <form action="#" method="post" id="overdrive-checkout-form">
+ <div class="modal-body">
+ <input type="hidden" name="id" value="" />
+ <fieldset class="brief">
+ <label for="format">Format:</label>
+ <ul class="overdrive-format-list">
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <input type="submit" class="btn btn-primary overdrive-checkout-submit" value="Checkout" />
+ <a href="#" data-dismiss="modal" aria-hidden="true" class="cancel">Cancel</a>
+ </div>
+ </form> <!-- /#overdrive-checkout-form -->
+</div> <!-- /#overdrive-checkout -->
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-overdrive-search.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-overdrive-search.tt
index 5f5a836..f5a26af 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-overdrive-search.tt
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-overdrive-search.tt
@@ -55,6 +55,8 @@
</div> <!-- / .container-fluid -->
</div> <!-- / .main -->
+[% INCLUDE 'overdrive-checkout.inc' %]
+
[% INCLUDE 'opac-bottom.inc' %]
[% BLOCK jsinclude %]
<script type="text/javascript" src="[% interface %]/[% theme %]/js/overdrive.js"></script>
@@ -80,7 +82,9 @@ function fetch_availability( prod, $tr ) {
$availability_summary.find( '.available' ).append( ', ' + _("waiting holds:") + ' <strong>' + data.numberOfHolds + '</strong>' );
}
- $tr.find( '.info' ).append( '<div class="actions-menu"><span class="actions"><a href="' + prod.contentDetails[0].href + '" ' + ( data.copiesAvailable ? ( ' class="addtocart">' + _("Check out") ) : ( ' class="hold">' + _("Place hold") ) ) + '</a></span></div>' );
+ $tr.find( '.info' ).each(function() {
+ KOHA.OverDriveCirculation.add_actions(this, data.id, data.copiesAvailable);
+ });
}
);
}
@@ -179,7 +183,16 @@ $( document ).ready( function() {
return false;
});
- search( 0 );
+ [% IF ( overdrive_error ) %]
+ KOHA.OverDriveCirculation.display_error("#breadcrumbs", "[% overdrive_error.dquote %]");
+ [% END %]
+ [% IF ( loggedinusername ) %]
+ KOHA.OverDriveCirculation.with_account_details("#breadcrumbs", function() {
+ search( 0 );
+ });
+ [% ELSE %]
+ search( 0 );
+ [% END %]
} );
</script>
[% END %]
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
index d45222e..70ad94d 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
@@ -119,8 +119,13 @@
[% IF ( BORROWER_INFO.amountlessthanzero ) %]<li><a href="#opac-user-fines">Credits ([% BORROWER_INFO.amountoutstanding %])</a></li>[% END %]
[% END %]
[% IF ( RESERVES.count ) %]<li><a href="#opac-user-holds">Holds ([% RESERVES.count %])</a></li>[% END %]
+ [% IF ( OverDriveCirculation ) %]
+ <li><a href="#opac-user-overdrive">OverDrive Account</a></li>
+ [% END %]
</ul>
+ <div id="opac-user-overdrive">
+ </div>
<div id="opac-user-checkouts">
[% IF ( issues_count ) %]
<form id="renewselected" action="/cgi-bin/koha/opac-renew.pl" method="post">
@@ -701,6 +706,10 @@
</div> <!-- /.container-fluid -->
</div> <!-- /#main -->
+[% IF ( OverDriveCirculation ) %]
+[% INCLUDE 'overdrive-checkout.inc' %]
+[% END %]
+
[% INCLUDE 'opac-bottom.inc' %]
@@ -764,4 +773,18 @@
});
//]]>
</script>
+ <script type="text/javascript" src="[% interface %]//[% theme %]/js/overdrive.js"></script>
+ <script type="text/JavaScript">
+ $(document).ready(function() {
+ [% IF ( overdrive_error ) %]
+ KOHA.OverDriveCirculation.display_error("#opac-user-overdrive", "[% overdrive_error.dquote %]");
+ [% END %]
+ [% IF ( overdrive_tab ) %]
+ $("#opac-user-views").tabs("select", "#opac-user-overdrive");
+ [% END %]
+ $("#opac-user-overdrive").each( function() {
+ KOHA.OverDriveCirculation.display_account_details(this);
+ } );
+ });
+ </script>
[% END %]
diff --git a/koha-tmpl/opac-tmpl/bootstrap/js/overdrive.js b/koha-tmpl/opac-tmpl/bootstrap/js/overdrive.js
index 1bc8c5d..e985d61 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/js/overdrive.js
+++ b/koha-tmpl/opac-tmpl/bootstrap/js/overdrive.js
@@ -59,3 +59,362 @@ KOHA.OverDrive = ( function() {
}
};
} )();
+
+KOHA.OverDriveCirculation = new function() {
+ var svc_url = '/cgi-bin/koha/svc/overdrive';
+
+ var error_div = $('<div class="overdrive-error">');
+ function display_error ( error ) {
+ error_div.text(error);
+ }
+
+ var login_link = $('<a href="#">')
+ .click(function(e) {
+ e.preventDefault();
+ login();
+ })
+ .text(_("Login to OverDrive account"));
+ var login_div = $('<div class="overdrive-login">').append(login_link);
+
+ var details = null;
+
+ function is_logged_in() {
+ return details ? details.is_logged_in : false;
+ }
+
+ var checkout_popup = null;
+ $( document ).ready(function() {
+ checkout_popup = $("#overdrive-checkout");
+ });
+
+ function display_account (container, data) {
+ if (!data.is_logged_in) {
+ $(container).append(login_div);
+ return;
+ }
+
+ var logout_link = $('<a href="#logout" class="overdrive-logout">')
+ .click(function(e) {
+ e.preventDefault();
+ $(container).empty().append(error_div);
+ logout(function(data) {
+ display_account(container, data);
+ });
+ }).text(_("Logout from OverDrive account"));
+ $(container).append(logout_link);
+
+ if (data.checkouts) {
+ var checkouts_div = $('<div class="overdrive-div">').html('<h3>' + _("Checkouts") + '</h3>');
+ var checkouts_list = $('<ul class="overdrive-list">');
+ data.checkouts.items.forEach(function(item) {
+ item_line(checkouts_list, item);
+ });
+ checkouts_div.append(checkouts_list);
+ $(container).append(checkouts_div);
+ }
+
+ if (data.holds) {
+ var holds_div = $('<div class="overdrive-div">').html('<h3>' + _("Holds") + '</h3>');
+ var holds_list = $('<ul class="overdrive-list">');
+ data.holds.items.forEach(function(item) {
+ item_line(holds_list, item);
+ });
+ holds_div.append(holds_list);
+ $(container).append(holds_div);
+ }
+ }
+
+ function item_line(ul_el, item) {
+ var line = $('<li class="overdrive-item">');
+ if (item.images) {
+ var thumb_url = item.images.thumbnail;
+ if (thumb_url) {
+ $('<img class="overdrive-item-thumbnail">')
+ .attr("src", thumb_url)
+ .appendTo(line);
+ }
+ }
+ $('<div class="overdrive-item-title">')
+ .text(item.title)
+ .appendTo(line);
+ $('<div class="overdrive-item-subtitle">')
+ .text(item.subtitle)
+ .appendTo(line);
+ $('<div class="overdrive-item-author">')
+ .text(item.author)
+ .appendTo(line);
+ var actions = $('<span class="actions">');
+ display_actions(actions, item.id);
+ $('<div id="action_'+item.id+'" class="actions-menu">')
+ .append(actions)
+ .appendTo(line);
+
+ $(ul_el).append(line);
+ }
+
+ function svc_ajax ( method, params, success_callback ) {
+ return $.ajax({
+ method: method,
+ dataType: "json",
+ url: svc_url,
+ data: params,
+ success: function (data) {
+ if (data.error) {
+ display_error(data.error);
+ }
+ success_callback(data);
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ display_error(errorThrown);
+ }
+ });
+ }
+
+ function load_account_details ( callback ) {
+ svc_ajax('get', { action: "account" }, function(data) {
+ details = data;
+ callback(data);
+ });
+ }
+
+ function login() {
+ svc_ajax('get', { action: "login" }, function(data) {
+ details = null;
+ if (data.login_url) {
+ window.location = data.login_url;
+ }
+ });
+ }
+
+ function logout (callback) {
+ svc_ajax('post', { action: "logout" }, function(data) {
+ details = null;
+ callback(data);
+ });
+ }
+
+ function item_action (params, el, copies_available) {
+ var id = params.id;
+ svc_ajax('post', params, function(data) {
+ if (data.checkouts) {
+ details.checkouts = data.checkouts;
+ }
+ if (data.holds) {
+ details.holds = data.holds;
+ }
+ display_actions(el, id, copies_available);
+ });
+ }
+
+ function item_is_checked_out (id) {
+ if ( !(details && details.checkouts) ) {
+ return null;
+ }
+ var id_uc = id.toUpperCase();
+ var items = details.checkouts.items;
+ for (var i = 0; i < items.length; i++) {
+ if ( items[i].id.toUpperCase() == id_uc ) {
+ return items[i];
+ }
+ }
+ return null;
+ }
+
+ function item_is_on_hold (id) {
+ if ( !(details && details.holds) ) {
+ return false;
+ }
+ var id_uc = id.toUpperCase();
+ var items = details.holds.items;
+ for (var i = 0; i < items.length; i++) {
+ if ( items[i].id.toUpperCase() == id_uc ) {
+ return items[i];
+ }
+ }
+ return null;
+ }
+
+ function display_actions(el, id, copies_available) {
+ $(el).empty();
+ if (is_logged_in()) {
+
+ var item = item_is_checked_out(id);
+ if (item) {
+ var expires = new Date(item.expires);
+ $('<span class="overdrive-item-status">')
+ .text(_("Checked out until") + " " + expires.toLocaleString())
+ .appendTo(el);
+ $(el).append(" ");
+
+ if (item.format) {
+ var download = $('<a href="#">').appendTo(el);
+ decorate_button(download, _("Download") + " " + item.format);
+ svc_ajax('get', {action: "download-url", id: id, format: item.format}, function(data) {
+ download.attr("href", data.action);
+ });
+ $(el).append(" ");
+ }
+
+ if (item.formats) {
+ var lockable_formats = [];
+ for (var f in item.formats) {
+ if (f == item.format) continue;
+
+ if (item.formats[f]) {
+ var access = $('<a target="_blank">').appendTo(el);
+ decorate_button(access, _("Access online") + " " + f);
+ svc_ajax('get', {action: "download-url", id: id, format: f}, function(data) {
+ access.attr("href", data.action);
+ });
+ $(el).append(" ");
+ }
+ else {
+ lockable_formats.push(f);
+ }
+ }
+ if (lockable_formats.length > 0 && checkout_popup) {
+ $(el).append( ajax_button(_("Download as"), function() {
+ checkout_format(el, id, lockable_formats, copies_available);
+ }) ).append(" ");
+ }
+ }
+
+ if (item.format) return item;
+
+ $(el).append( ajax_button(_("Check in"), function() {
+ if( confirm(_("Are you sure you want to return this item?")) ) {
+ item_action({action: "return", id: id}, el, copies_available + 1);
+ }
+ }) );
+
+ return item;
+ }
+
+ item = item_is_on_hold(id);
+ if (item) {
+ $('<span class="overdrive-status">')
+ .text(_("On hold"))
+ .appendTo(el);
+ $(el).append(" ");
+ }
+
+ if(copies_available && checkout_popup) {
+ $(el).append( ajax_button(_("Check out"), function() {
+ if( confirm(_("Are you sure you want to checkout this item?")) ) {
+ svc_ajax('post', {action: "checkout", id: id}, function(data) {
+ if (data.checkouts) {
+ details.checkouts = data.checkouts;
+ }
+ if (data.holds) {
+ details.holds = data.holds;
+ }
+ item = display_actions(el, id, copies_available - 1);
+ if (item && item.formats && !item.format) {
+ var has_available_formats = false;
+ var lockable_formats = [];
+ for (var f in item.formats) {
+ if (item.formats[f]) {
+ has_available_formats = true;
+ break;
+ }
+ lockable_formats.push(f);
+ }
+
+ if (!has_available_formats) {
+ checkout_format(el, id, lockable_formats, copies_available - 1);
+ }
+ }
+ });
+ }
+ }) );
+ }
+ else if (!item) {
+ $(el).append( ajax_button(_("Place hold"), function() {
+ item_action({action: "place_hold", id: id}, el, copies_available);
+ }) );
+ }
+
+ if (item) {
+ $(el).append( ajax_button(_("Cancel"), function() {
+ if( confirm(_("Are you sure you want to cancel this hold?")) ) {
+ item_action({action: "return", id: id}, el, copies_available);
+ }
+ }) );
+ }
+ return item;
+ }
+ }
+
+ function ajax_button(label, on_click) {
+ var button = $('<a href="#">')
+ .click(function(e) {
+ e.preventDefault();
+ on_click();
+ });
+ decorate_button(button, label);
+ return button;
+ }
+
+ function decorate_button(button, label) {
+ $(button)
+ .addClass("btn btn-primary btn-mini")
+ .css("color","white")
+ .text(label);
+ }
+
+ function checkout_format(el, id, formats, copies_available) {
+ if (formats.length == 0) {
+ alert(_("Item cannot be checked out - no available formats"));
+ return false;
+ }
+
+ var checkout_format_list = checkout_popup.find("ul.overdrive-format-list").empty();
+ formats.forEach(function (item) {
+ var li = $('<li>').appendTo(checkout_format_list);
+ $('<input name="checkout-format" type="radio">')
+ .val(item)
+ .appendTo(li);
+ li.append(item);
+ });
+ checkout_popup.modal("show");
+ checkout_popup.find(".overdrive-checkout-submit").click(function(e) {
+ e.preventDefault();
+ var format = checkout_format_list.find("input[type='radio'][name='checkout-format']:checked").val();
+ item_action({action: "checkout-format", id: id, format: format}, el, copies_available);
+ $(this).unbind( e );
+ checkout_popup.modal("hide");
+ });
+ }
+
+ this.with_account_details = function( el, callback ) {
+ $(el).append(error_div);
+ load_account_details(function(data) {
+ if (!data.is_logged_in) {
+ $(el).append(login_div);
+ }
+ callback(data);
+ });
+ }
+
+ this.display_account_details = function( el ) {
+ $(el).empty().append(error_div);
+ load_account_details(function(data) {
+ display_account(el, data);
+ });
+ };
+
+ this.display_error = function( el, error ) {
+ $(el).empty().append(error_div);
+ display_error(error);
+ };
+
+ this.is_logged_in = is_logged_in;
+
+ this.add_actions = function(el, id, copies_available) {
+ var actions = $('<span class="actions">');
+ display_actions(actions, id, copies_available);
+ $('<div id="action_'+id+'" class="actions-menu">')
+ .append(actions)
+ .appendTo(el);
+ };
+}
diff --git a/opac/opac-overdrive-search.pl b/opac/opac-overdrive-search.pl
index dbf60af..1f8304b 100755
--- a/opac/opac-overdrive-search.pl
+++ b/opac/opac-overdrive-search.pl
@@ -41,5 +41,6 @@ $template->{'VARS'}->{'q'} = $cgi->param('q');
$template->{'VARS'}->{'limit'} = C4::Context->preference('OPACnumSearchResults') || 20;
$template->{'VARS'}->{'OPACnumSearchResults'} = C4::Context->preference('OPACnumSearchResults') || 20;
$template->{'VARS'}->{'OverDriveLibraryID'} = C4::Context->preference('OverDriveLibraryID');
+$template->param(overdrive_error => $cgi->param('overdrive_error'));
output_html_with_http_headers $cgi, $cookie, $template->output;
diff --git a/opac/opac-user.pl b/opac/opac-user.pl
index 0828739..05141d6 100755
--- a/opac/opac-user.pl
+++ b/opac/opac-user.pl
@@ -313,6 +313,12 @@ if (C4::Context->preference("OPACAmazonCoverImages") or
$template->param(JacketImages=>1);
}
+$template->param(
+ OverDriveCirculation => C4::Context->preference('OverDriveCirculation') || 0,
+ overdrive_error => $query->param('overdrive_error') || undef,
+ overdrive_tab => $query->param('overdrive_tab') || 0,
+);
+
my $patron_messages = Koha::Patron::Messages->search(
{
borrowernumber => $borrowernumber,
diff --git a/opac/svc/overdrive b/opac/svc/overdrive
new file mode 100755
index 0000000..ea20915
--- /dev/null
+++ b/opac/svc/overdrive
@@ -0,0 +1,139 @@
+#!/usr/bin/perl
+
+# script to log clicks on links to external urls
+
+# Copyright 2015 Catalyst IT
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+use CGI qw ( -utf8 );
+use JSON qw(encode_json);
+use C4::Auth qw(checkauth);
+use C4::Output;
+use Koha::Logger;
+use Koha::ExternalContent::OverDrive;
+
+my $logger = Koha::Logger->get({ interface => 'opac' });
+my $cgi = new CGI;
+my $page_url = $cgi->referer();
+
+my ( $user, $cookie, $sessionID, $flags ) = checkauth( $cgi, 1, {}, 'opac' );
+$user && $sessionID or response_bad_request("User not logged in");
+
+my $action = $cgi->param('action') or response_bad_request("No 'action' specified");
+
+my $od = Koha::ExternalContent::OverDrive->new({ koha_session_id => $sessionID });
+my %data = (
+ is_logged_in => JSON::false,
+);
+local $@;
+eval {
+ {
+ $action eq 'login' && do {
+ $data{login_url} = $od->auth_url($page_url);
+ last;
+ };
+
+ if ($od->is_logged_in) {
+ $data{is_logged_in} = JSON::true;
+
+ $action eq 'logout' && do {
+ $od->forget();
+ $data{login_url} = $od->auth_url($page_url);
+ $data{is_logged_in} = JSON::false;
+ last;
+ };
+
+ $action eq 'account' && do {
+ $data{account} = $od->patron;
+ $data{checkouts} = $od->checkouts;
+ $data{holds} = $od->holds;
+ last;
+ };
+
+ $action eq 'checkout' && do {
+ my $id = $cgi->param('id')
+ or response_bad_request("No 'id' specified");
+ my $format = $cgi->param('format');
+ $data{action} = $od->checkout($id, $format);
+ $data{checkouts} = $od->checkouts;
+ $data{holds} = $od->holds;
+ last;
+ };
+
+ $action eq 'checkout-format' && do {
+ my $id = $cgi->param('id')
+ or response_bad_request("No 'id' specified");
+ my $format = $cgi->param('format')
+ or response_bad_request("No 'format' specified");
+ $data{action} = $od->lock_format($id, $format);
+ $data{checkouts} = $od->checkouts;
+ last;
+ };
+
+ $action eq 'download-url' && do {
+ my $id = $cgi->param('id')
+ or response_bad_request("No 'id' specified");
+ my $format = $cgi->param('format')
+ or response_bad_request("No 'format' specified");
+ $data{action} = $od->checkout_download_url($id, $format, $page_url, $page_url);
+ last;
+ };
+
+ $action eq 'place_hold' && do {
+ my $id = $cgi->param('id')
+ or response_bad_request("No 'id' specified");
+ $data{action} = $od->place_hold($id);
+ $data{holds} = $od->holds;
+ last;
+ };
+
+ $action eq 'return' && do {
+ my $id = $cgi->param('id')
+ or response_bad_request("No 'id' specified");
+ $data{action} = $od->return($id);
+ $data{checkouts} = $od->checkouts;
+ $data{holds} = $od->holds;
+ last;
+ };
+
+ response_bad_request("Invalid 'action': $action");
+ }
+ }
+};
+if ($@) {
+ if ($od->is_not_authenticated_error($@)) {
+ $logger->debug("OverDrive session timeout");
+ $data{is_logged_in} = JSON::false;
+ } else {
+ $logger->error($@);
+ $data{error} = $od->error_message($@);
+ }
+}
+
+response(\%data);
+
+
+sub response_bad_request {
+ my ($error) = @_;
+ response({error => $error}, "400 $error");
+}
+sub response {
+ my ($data, $status_line) = @_;
+ $status_line ||= "200 OK";
+ output_with_http_headers $cgi, undef, encode_json($data), 'json', $status_line;
+ exit;
+}
--
1.9.1
More information about the Koha-patches
mailing list